Подтвердить что ты не робот

Оператор '==' не может применяться к типам 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

4b9b3361

Ответ 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;

Если компилятор знает это, вы, вероятно, тоже это знали.