错误消息的措辞可能具有误导性。将“无重叠”解释为不可能同时具有两种类型的值是合理的
this
类型
Derived
,这显然不是真的。错误信息曾经更糟糕,说“这种比较总是
false
“而不是”这似乎是无意的“。已更改,请参阅
microsoft/TypeScript#27910
,但关于“没有重叠”的困惑仍然存在,人们已经提出了反对它的问题,比如
microsoft/TypeScript#60583
和
microsoft/TypeScript#44645
和
microsoft/TypeScript#37155
其中一些被归类为bug,但通常当TS团队给出解释时,错误的存在不是bug,而是
消息
可以改进。
实际情况是,TypeScript有各种启发式方法来确定是否使用比较运算符,如
===
很可能是有意的,也不太可能是故意的。第一个近似值是:
expr1 === expr2
如果类型为
expr1
是
compatible with
类型
expr2
反之亦然。这里的“兼容”是指“可分配给”或“的子类型”或“缩小”。细节并不重要。
就你的情况而言,你不能分配
这
为类型的值
衍生
,也不能分配
bar
为类型的值
这
,因此两者都不能分配给另一个。所以TypeScript认为这表明你的比较可能是无意的。在类似的情况下,开发人员很乐意收到错误消息,因为他们确实写错了东西。正如前文所述
a comment of microsoft/TypeScript#44645
:
当我们稍微收紧这些检查时,我们会在实际代码中发现大量实际错误。
你可能会犯各种各样的错误
===
这些不是
可证明的
总是假的,但不太可能是故意的。在奇怪的代码中发出少量误报,在糟糕的代码中得到真阳性,这是所有类型检查器故意做出的权衡。
如果TypeScript将你的比较标记为可能是无意的,但你确实是认真的,你可以
拓宽
将一方与另一方的超类型进行比较。正如你所说,
这
和
衍生
两者都是类型
Base
因此,请将两侧拓宽至
基地
并且错误消失了:
if (this as Base === bar) { }
if (this === bar as Base) { }
最简单的方法是使用
type assertion
扩大,但由于类型断言也可能不安全地缩小,您可能更愿意避免或补充一些更安全的东西:
const thisBase: Base = this; if (thisBase === bar) { }
if (this satisfies Base as Base === bar) { }
无论如何,你都必须跳过一个小圈子,让TypeScript相信你是故意这样做的。这不是最优的,但每次“哦,拜托,这显然是故意的”,结果都有不少“哦,这实际上是个错误”。这类事情本质上总是具有启发性的,由于开发人员的意图不能被完美地捕捉到,他们能做的最好的事情就是尝试找到权衡最大化的地方
平均的
开发者体验。
Playground link to code