Оператор '==' не может применяться к типам x и y в Typescript 2
TypeScript Версия: 2.0.2.0
код
Я знаю, что код немного глуп, но у меня на самом деле есть такие тесты в моем коде (создание посетителя выражения), и я действительно думаю, что они должны летать и компилироваться сразу.
var a: boolean = (true == false);
var b: boolean = (5 == 2);
Вместо этого он жалуется, что равный операнд не может применяться к типам "true", "false", "5" и "2". Отметьте, что они не являются логическими или числовыми, они на самом деле являются типами "истина", "ложь", "5", "2". Я знаю, что типы 'string' и 'boolean' не могут сравниться, но hey, 5 на самом деле число, а не тип '5', или я ошибаюсь?
Это компилируется.
let x = 2;
var a: boolean = 5 == x;
var b: boolean = <number>5 == <number>2;
Я что-то упускаю, почему не 5 и 2 не считают типом числа?
Ожидаемое поведение:
Должен компилироваться
Фактическое поведение:
Результаты с компиляционной ошибкой: "Операнд" == 'не может применяться к типам "< first argument > "; и '< second argument > '
Фон Я столкнулся с этими проблемами в typescript, определяя, что это должно быть так, но как получилось?
https://github.com/Microsoft/TypeScript/issues/6167
Ответы
Ответ 1
Литеральные типы имеют много преимуществ, поскольку это позволяет компилятору сделать типы как можно более узкими. Ваш случай использования - это тот, который возникает очень редко, но желание типов быть настолько узким, насколько это возможно, пронизывает весь дизайн языка. Так что да, хотя это делает вашу жизнь труднее в этом конкретном случае, это имеет смысл на языке в целом. Пользователям придется страдать значительно хуже, просто чтобы поддержать этот один редкий случай использования.
К сожалению, вам придется использовать явный набор текста, который вы предлагаете себе во втором примере. Я не вижу, чтобы это когда-либо фиксировалось, потому что большинство пользователей хотят, чтобы язык кричал, если они попытаются это сделать. Вероятно, это признак ошибки в большинстве случаев.
Ответ 2
почему 5 и 2 не рассматриваются как типы 'number'
У них есть буквальный тип 5
и 2
. например
var x: 5;
// can only ever be assigned to 5
x = 5; // okay
x = 2; // Error
Я не вижу фактического варианта использования для того, чтобы он не был ошибкой. Это просто компилятор, который пытается вам помочь. Не стесняйтесь создавать проблему, если вы видите достаточную мотивацию
Ответ 3
Как разработчик Erlang, я видел такие ошибки в Erlang, но не знал, что это значит в TypeScript, вот пример, который поможет вам понять проблему:
let answer: "yes" | "no" | "maybe" = "yes";
if (Math.random() > 0.5) {
answer = "maybe";
}
if (answer === "yes") {
console.log('yes');
}
if (answer === "no") {
console.log('no');
}
Он не будет компилироваться с ошибкой:
error TS2365: Operator '===' cannot be applied to types '"yes" | "maybe"' and '"no"'.
Во-первых, здесь решение
let answer = "yes" as "yes" | "no" | "maybe";
Теперь объяснение:
Поскольку этот код очень прост и может быть понят во время компиляции, TypeScript знает, что там, где код answer
не может стать "no"
, там нет, поэтому он просто говорит вам (хотя и в довольно загадочной форме) этот ответ всегда не "нет", поэтому в буквальном смысле нет причин когда-либо проверять его. Но (как в Erlang) это может произойти по вполне очевидной причине, когда вы, например, решили прокомментировать какой-то код для отладки, который делал answer
, чтобы стать "no"
. Теперь, если мы используем let answer = "yes" as "yes" | "no" | "maybe";
или let answer = <("yes" | "no" | "maybe")>"yes";
, он сделает TypeScript полагать, что "да" может быть "нет", даже если вы не видите его в коде. Итак, для случая временно удалённого кода существует второе решение:
if (0) {
answer = "no";
}
Несмотря на то, что это условие никогда не будет истинным, это достаточно сложно для компилятора TypeScript, чтобы думать, что это может быть правдой. Мой подход Erlang заключается в использовании when X and not X
, который был бы if (x && !x) {
, но по крайней мере в 2.4 вы можете просто использовать числовые выражения.
Но в какой-то момент компилятор может быть прав, а затем solution должен удалить проверку для "no"
:)
Итак, возвращаясь к вопросу OP, чтобы сделать ваш код компилируемым, вам нужно изменить его на:
var a = false;
var b = false;
Если компилятор знает это, вы, вероятно, тоже это знали.