Typescript 基于条件类型的扩展行为不符合预期

Mar*_*ťko 2 type-inference typescript typescript-generics conditional-types

假设我们有这个例子:

class Base<T extends Base<T>> {}
class ClassA extends Base<ClassA> {}
class ClassB extends Base<ClassB> {}
type Condition = ClassA extends ClassB ? true : false;
Run Code Online (Sandbox Code Playgroud)

基类有一个通用参数,它基本上说,从它派生的任何东西都应该使用它自己的类型对其进行模板化。

然后我们有 2 个从所述基派生的类。

最后,我创建了一个条件类型来检查派生类是否相互扩展。

令我惊讶的是,打字稿告诉我确实如此,但我认为这个条件应该是错误的。ClassA不延伸ClassB,反之亦然。只ClassA extends Base<ClassA>应该返回true。

这是打字稿条件类型的问题还是我遗漏了什么?我在构建更复杂的条件类型时遇到了这个问题,它也返回了意外的结果。

编辑:也不需要通用参数。即使这个例子也返回错误的结果:

class Base {}
class ClassA extends Base {}
class ClassB extends Base {}
type Condition = ClassA extends ClassB ? true : false;
Run Code Online (Sandbox Code Playgroud)

Tit*_*mir 7

Typescript 使用结构类型来最好地模拟 Javascript 鸭子类型的工作方式。这样做的好处是允许我们以静态类型的方式对许多 Javascript 场景进行建模。

问题是,您永远不能忘记,当 typescript 检查任何类型兼容性(即使是条件类型)时,它并不是像 C# 或 Java 那样检查名义继承,而是检查结构子类型。

在您的示例中,由于所有类都是空的,因此它们在结构上等同于{},这意味着是的,ClassA确实扩展ClassBClassB扩展ClassA,因为它们在结构上都是相同的类型。

将任何成员添加到类中,这种情况就会消失,私有成员确保最大程度的不兼容性,因为另一个类(或接口)不能只是声明重新声明它们来模拟子类型。

class Base {}
class ClassA extends Base { private a: number}
class ClassB extends Base { private b: number}
type Condition = ClassA extends ClassB ? true : false; // false now
Run Code Online (Sandbox Code Playgroud)