这种比较似乎是无意的,因为类型“this”和“Derived”没有重叠

问题描述 投票:0回答:1

我有一个类

Base
和一个继承自它的类
Derived
Base
有一个方法,将
Derived
作为参数并将
this
与其进行比较:

class Base {
    foo(bar: Derived): void {
        if(this === bar){
            return;
        }
        //Do stuff
    }
}

class Derived extends Base {
    baz(): void {}
}

游乐场链接

当我尝试编译它时,出现此错误:

error TS2367: This comparison appears to be unintentional because the types
 'this' and 'Derived' have no overlap.

3         if(this === bar){
             ~~~~~~~~~~~~

我不明白为什么会出现此错误,

this
Derived
都是
Base
类型,所以它们do有重叠。如果我执行
const x = new Derived(); x.foo(x);
,它将进入
if
块,因此比较并非像编译器认为的那样毫无用处。

有趣的是,如果我删除

baz()
方法,使
Derived
具有空主体,错误就会消失(但这并不能解决我的问题,因为拥有空主体的类没有多大意义)。

为什么会出现此错误以及如何修复它?

typescript inheritance
1个回答
0
投票

错误消息的措辞可能具有误导性。将“无重叠”解释为不可能同时具有

this
类型和
Derived
类型的值是合理的,这显然是不正确的。错误消息曾经更糟糕,并说“这种比较总是
false
”而不是“这似乎是无意的”。这已更改,请参阅 microsoft/TypeScript#27910,但关于“无重叠”的困惑仍然存在,人们已经针对它提出了问题,例如 microsoft/TypeScript#60583microsoft/TypeScript#44645microsoft/ TypeScript#37155。其中一些被归类为错误,但通常当 TS 团队给出解释时,错误的存在不是错误,但消息可以改进。

实际发生的情况是,TypeScript 有各种启发式方法来确定像

===
这样的比较运算符的使用可能是有意的还是不太可能是有意的。初步近似,规则是:如果
expr1 === expr2
的类型与
expr1
的类型兼容,则允许 expr2
,反之亦然。 “兼容”在这里意味着“可分配给”或“子类型”或“缩小范围”。细节并不是特别重要。

在您的情况下,您不能将

this

 分配给 
Derived
 类型的值,也不能将 
bar
 分配给 
this
 类型的值,因此两者都不能分配给另一个。因此 TypeScript 认为这表明您的比较可能是无意的。在类似的情况下,开发人员会很高兴收到该错误消息,因为他们确实写了错误的东西。正如 
microsoft/TypeScript#44645 的评论中提到的

这些检查,当我们稍微收紧它们时,我们就会在实际代码中发现大量实际错误。

使用

===

 可能会犯各种各样的错误,这些错误并非“可证明”总是错误的,但不太可能是故意的。在奇怪的代码中发出少量误报以在糟糕的代码中获得真阳性是所有类型检查器有意做出的权衡。
在 TypeScript 将您的比较标记为可能无意的但您确实是这么想的情况下,您可以

扩大
比较的一侧与另一侧的超类型。 正如你所说,

thisDerived

都是
Base
类型。因此,将任一侧加宽到 
Base
,错误就会消失:
if (this as Base === bar) { }
if (this === bar as Base) { }

最简单的方法是使用
类型断言
来扩大,但由于类型断言也可能不安全地缩小范围,您可能更愿意避免或用更安全的东西来补充它:

const thisBase: Base = this; if (thisBase === bar) { } if (this satisfies Base as Base === bar) { }

无论如何,你都必须克服一些困难才能让 TypeScript 相信你是故意这样做的。这不是最佳的,但对于每一个“哦,拜托,这显然是故意的”,结果都会有相当多的“哦,这实际上是一个错误”。这类事情本质上总是启发式的,并且由于无法完美捕捉开发人员的意图,因此他们能做的最好的事情就是尝试找到权衡最大化“平均”开发人员体验的地方。

Playground 代码链接

© www.soinside.com 2019 - 2024. All rights reserved.