2

I have read Operator '==' cannot be applied to types x and y in Typescript 2 and it has not been informative to my case.

In TypeScript 2.5.3, we define many models using string enums of the form:

export interface Event {
   category: "MORNING" | "NIGHT";
   enabled: boolean;
}

And then apply comparators to them like:

morning = events.filter(event => event.category === 'MORNING');

without complaint.

Now, in this code fragment:

if (event.enabled || event.category === 'MORNING') {
 // something
}
else if (event.category !== 'MORNING') {
 // something else
}

I get the Operator '!==' cannot be applied to types '"MORNING"' and '"NIGHT"' compile error in the else if condition, but not in the if condition, which uses the same (but opposite) comparator.

Reducing the example further, the following compiles:

if (event.category !== 'MORNING') {
 // something
}
else if (event.category !== 'MORNING') {
 // something else
}

And this compiles:

if (event.category !== 'MORNING') {
 // something
}
else if (event.category === 'MORNING') {
 // something else
}

Whereas this throws an error (in the else if line):

if (event.category === 'MORNING') {
 // something
}
else if (event.category !== 'MORNING') {
 // something else
}

What fundamental property of the type-checker have I misunderstood?

(Note: The final examples are reduced from more complex situations, so I cannot use a simple else.)

4

2 回答 2

4

你会得到一个错误,因为编译器已经知道在else if条件点,event.category不是'MORNING'并且将不再允许你与event.category它进行比较。

如果此条件计算为false

if (event.enabled || event.category === 'MORNING') {
 // something
}

那么根据定义,event.category不是,因此 。编译器不允许您再次比较它(实际上没有必要再次比较它),因为已经知道它不在评估条件的时候。'MORNING''NIGHT''MORNING''MORNING''MORNING'else if

顺便说一句,由于基本相同的原因,以下内容会产生编译错误:

if (event.category !== 'MORNING') {
 // something
}
else if (event.category !== 'NIGHT') {
 // something else
}

就像这样:

if (event.category === 'MORNING' || event.category !== 'MORNING') {
 // something
}

这是由于 TypeScript 在评估后续布尔表达式时“缩小”联合类型的方式。

如以下评论中所建议,请参阅https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-0.html#control-flow-based-type-analysis,以及https:// /github.com/Microsoft/TypeScript/blob/master/doc/spec.md#4.24

于 2017-11-03T17:59:03.083 回答
1

我认为这是正确的,并且与 Typescript 和 TypeGuards 中的类型检查系统有关。考虑:

你的拳头例子:

if (event.category !== 'MORNING') {
 // something
}
else if (event.category === 'MORNING') {
 // something else
}

在第一次if打字稿不能假设任何关于category. 简单检查某物是否不等于某种值并不能告诉我们有关变量类型的任何信息。在它的下一个链中else if可能是任何与您的变量类型匹配的东西。

不工作的例子:

if (event.category === 'MORNING') {
 // something
}
else if (event.category !== 'MORNING') {
 // something else
}

但是如果你反过来检查,你肯定知道category不能等于'MORNING',所以 Typescript 会改变你的类型。它是某种类型的缩小。

https://github.com/Microsoft/TypeScript/blob/master/doc/spec.md#424-type-guards规范 C 中的更多信息:

于 2017-11-03T18:04:38.380 回答