我不能在TypeScript的超类方法中使用子类类型

mfuanj7w  于 2023-04-13  发布在  TypeScript
关注(0)|答案(1)|浏览(111)

假设我有这个代码:

class SuperElement extends Something {
  render(subclassInstance: ???) {}
}

class MyElement extends SuperElement {
  render({ sayHello }) {
    sayHello('Foo');
  }

  sayHello(name: string);
}

有没有一种方法可以让我的IDE在render中正确地自动完成(在MyElement中)?
我试着使用(subclassInstance: this),但它不工作。

nhn9ugyo

nhn9ugyo1#

从概念上讲,您确实希望使用多态this类型来表示潜在子类的类型。这本质上是一个隐式的generic类型参数,它被约束到实现类,只有在以后作为方法调用时才被指定:

class SuperElement {
  render(subclassInstance: this) { }
}

new SuperElement().render;
// (method) SuperElement.render(subclassInstance: SuperElement): void
// this type inferred to be --------------------> ^^^^^^^^^^^^

class SomeSubElement extends SuperElement {
  foo = 123;
}    
new SomeSubElement().render;
// (method) SuperElement.render(subclassInstance: SomeSubElement): void
// this type inferred to be --------------------> ^^^^^^^^^^^^^^

不幸的是,当你在TypeScript中重写方法时,子类并不能从超类类型中推断出它的参数类型。你必须自己注解它们,然后它将根据超类方法参数类型进行 * 检查 * 以确保兼容性。这是TypeScript中一个长期存在的痛点;要求从父类继承参数类型的相关公开问题是microsoft/TypeScript#23911。除非实现了,否则,你只能这样做:

class MyElement extends SuperElement {
  render({ sayHello }: this) {
    // annotate ---> ^^^^^^
    sayHello('Foo');
  }    
  sayHello(name: string) {}
}

这不是很好,但至少可以捕获错误:

class OopsElement extends SuperElement {
  render({ sayHowdy }: this) { // error!
    //     ~~~~~~~~ <--
    // Property 'sayHowdy' does not exist on type 'OopsElement'    
  }
  sayHello(name: string) {}
}

Playground链接到代码

相关问题