运算符“==”不能应用于 Typescript 2 中的类型 x 和 y
Operator '==' cannot be applied to types x and y in Typescript 2
TypeScript 版本: 2.0.2.0
代码
我知道代码有点愚蠢,但实际上我的代码中有这类测试(创建表达式访问者),我真的认为这些应该立即运行并编译。
var a: boolean = (true == false);
var b: boolean = (5 == 2);
相反,它抱怨操作数等于不能应用于类型 'true'、'false'、'5' 和 '2'。标记它们不是布尔值或数字,它们实际上是'true'、'false'、'5'、'2'的一种类型。我知道类型 'string' 和 'boolean' 无法比较,但是嘿,5 实际上是一个数字,而不是类型“5”,还是我弄错了?
虽然编译。
let x = 2;
var a: boolean = 5 == x;
var b: boolean = <number>5 == <number>2;
我是不是漏掉了什么,为什么 5 和 2 不被视为 'number' 类型?
预期行为:
应该编译
实际行为:
导致编译错误说 'Operand '==' cannot be applied to types '' and ''
背景 我在打字稿中遇到了这个问题定义它应该是这样的,但是怎么会呢?
https://github.com/Microsoft/TypeScript/issues/6167
why aren't 5 and 2 considered as type 'number'
它们具有文字类型 5
和 2
。例如
var x: 5;
// can only ever be assigned to 5
x = 5; // okay
x = 2; // Error
我没有看到希望它不是错误的实际用例。这只是编译器试图帮助你。如果你看到足够的动机,请随意创建一个问题
文字类型有很多优点,因为它让编译器使类型尽可能窄。您的用例很少出现,但希望类型尽可能窄贯穿了语言的整个设计。所以是的,虽然在这个特定情况下它会让你的生活变得更加艰难,但它在整个语言中都是有意义的。用户将不得不忍受一种更糟糕的语言,只是为了支持这个罕见的用例。
不幸的是,您将不得不使用您在第二个示例中建议的显式类型。我没有看到这个问题得到解决,因为大多数用户 想要 如果他们试图这样做,语言就会大喊大叫。在大多数情况下,这可能是错误的迹象。
作为 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"
,所以它只是告诉你(尽管在相当神秘的形式)答案总是不是 "no",所以实际上没有理由去检查它是否是。但是(在 Erlang 中)这可能出于非常明显的原因而发生,例如,当您决定注释掉一些使 answer
变为 "no"
的调试代码时。现在如果我们使用 let answer = "yes" as "yes" | "no" | "maybe";
或 let answer = <("yes" | "no" | "maybe")>"yes";
它会让 TypeScript 认为 "yes" 可以是 "no" 即使你在代码中看不到它。因此,对于暂时删除代码的情况,有 第二种解决方案 :
if (0) {
answer = "no";
}
即使这个条件永远不会为真,但 "complex" 足以让 TypeScript 编译器认为它可以为真。我的 Erlang 方法是使用 when X and not X
也就是 if (x && !x) {
但至少在 2.4 中你可以只使用数字表达式。
但在某些时候编译器可能是正确的然后解决方案是删除对"no"
的检查:)
因此将其返回到 OP 的问题,要使您的代码编译,您需要将其更改为:
var a = false;
var b = false;
如果编译器知道,您可能也知道。
在以下场景中遇到相同的问题:
let a: string;
a === 'some-value1' && a === 'some-value2'; // <==
第二行产生相同的错误,可能是因为 Typescript 聪明 足以知道给定时刻的字符串类型不能包含两个(或更多)不同的字符串文字。
上述表达式的正确方法是在表达式中使用 OR:
a === 'some-value1' || a === 'some-value2'; // works fine :)
TypeScript 版本: 2.0.2.0
代码 我知道代码有点愚蠢,但实际上我的代码中有这类测试(创建表达式访问者),我真的认为这些应该立即运行并编译。
var a: boolean = (true == false);
var b: boolean = (5 == 2);
相反,它抱怨操作数等于不能应用于类型 'true'、'false'、'5' 和 '2'。标记它们不是布尔值或数字,它们实际上是'true'、'false'、'5'、'2'的一种类型。我知道类型 'string' 和 'boolean' 无法比较,但是嘿,5 实际上是一个数字,而不是类型“5”,还是我弄错了?
虽然编译。
let x = 2;
var a: boolean = 5 == x;
var b: boolean = <number>5 == <number>2;
我是不是漏掉了什么,为什么 5 和 2 不被视为 'number' 类型?
预期行为: 应该编译
实际行为:
导致编译错误说 'Operand '==' cannot be applied to types '
背景 我在打字稿中遇到了这个问题定义它应该是这样的,但是怎么会呢? https://github.com/Microsoft/TypeScript/issues/6167
why aren't 5 and 2 considered as type 'number'
它们具有文字类型 5
和 2
。例如
var x: 5;
// can only ever be assigned to 5
x = 5; // okay
x = 2; // Error
我没有看到希望它不是错误的实际用例。这只是编译器试图帮助你。如果你看到足够的动机,请随意创建一个问题
文字类型有很多优点,因为它让编译器使类型尽可能窄。您的用例很少出现,但希望类型尽可能窄贯穿了语言的整个设计。所以是的,虽然在这个特定情况下它会让你的生活变得更加艰难,但它在整个语言中都是有意义的。用户将不得不忍受一种更糟糕的语言,只是为了支持这个罕见的用例。
不幸的是,您将不得不使用您在第二个示例中建议的显式类型。我没有看到这个问题得到解决,因为大多数用户 想要 如果他们试图这样做,语言就会大喊大叫。在大多数情况下,这可能是错误的迹象。
作为 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"
,所以它只是告诉你(尽管在相当神秘的形式)答案总是不是 "no",所以实际上没有理由去检查它是否是。但是(在 Erlang 中)这可能出于非常明显的原因而发生,例如,当您决定注释掉一些使 answer
变为 "no"
的调试代码时。现在如果我们使用 let answer = "yes" as "yes" | "no" | "maybe";
或 let answer = <("yes" | "no" | "maybe")>"yes";
它会让 TypeScript 认为 "yes" 可以是 "no" 即使你在代码中看不到它。因此,对于暂时删除代码的情况,有 第二种解决方案 :
if (0) {
answer = "no";
}
即使这个条件永远不会为真,但 "complex" 足以让 TypeScript 编译器认为它可以为真。我的 Erlang 方法是使用 when X and not X
也就是 if (x && !x) {
但至少在 2.4 中你可以只使用数字表达式。
但在某些时候编译器可能是正确的然后解决方案是删除对"no"
的检查:)
因此将其返回到 OP 的问题,要使您的代码编译,您需要将其更改为:
var a = false;
var b = false;
如果编译器知道,您可能也知道。
在以下场景中遇到相同的问题:
let a: string;
a === 'some-value1' && a === 'some-value2'; // <==
第二行产生相同的错误,可能是因为 Typescript 聪明 足以知道给定时刻的字符串类型不能包含两个(或更多)不同的字符串文字。
上述表达式的正确方法是在表达式中使用 OR:
a === 'some-value1' || a === 'some-value2'; // works fine :)