如何在 Typescript 中表示抽象类的任何子类的类型?

Vic*_*ira 2 oop inheritance abstract-class node.js typescript

假设

abstract class A {};
class B extends A {};
class C extends A {};
Run Code Online (Sandbox Code Playgroud)

我想接受 A 的任何子类作为参数。

function foo(Subclass: A){
   const obj = new Subclass();
}
Run Code Online (Sandbox Code Playgroud)

这行不通。我收到错误

该表达式不可构造。类型“BaseController”没有构造签名。

然后我尝试了

function foo(Subclass: typeof A){   
   const obj = new Subclass();
}
Run Code Online (Sandbox Code Playgroud)

现在我得到了错误

无法创建抽象类的实例.ts(2511)

因为它假设我传递的是 A 而不是 A 的子类。

可以实现吗?我该如何让它发挥作用?

jca*_*alz 6

我认为你应该将注释更改为以下内容:

function foo(subclass: new () => A) {
  const obj = new subclass();
}
Run Code Online (Sandbox Code Playgroud)

在这里,我们说的subclassnew能够(即,它是您使用new运算符调用的构造函数),不带参数,并构造一个类型可分配给 的值A。这应该接受任何具体子类,A只要它有一个无参数构造函数:

foo(B); // okay
foo(C); // okay
Run Code Online (Sandbox Code Playgroud)

它不会接受A自身,因为抽象类构造函数不被认为new能够:

foo(A); // error, A is abstract
Run Code Online (Sandbox Code Playgroud)

哦,作为为 Stack Overflow 问题制作示例 TypeScript 代码的人的注释:请注意,TypeScript 的类型系统是结构化的。根据您给出的示例定义,AB、 和的实例C被视为相同的类型。所有对象都可以分配给空类型,所以这也有效:

foo(Date); // okay also
Run Code Online (Sandbox Code Playgroud)

为了防止这种情况,您应该向AB和/或添加属性C以在结构上区分它们,例如:

abstract class A {
  a = "A"
};
class B extends A {
  b = "B"
};
class C extends A {
  c = "C"
};
Run Code Online (Sandbox Code Playgroud)

这将导致更多预期的行为:

foo(B); // okay
foo(C); // okay
foo(A); // error, A is abstract
foo(Date); // error, 'a' is missing
Run Code Online (Sandbox Code Playgroud)

好的,希望有帮助;祝你好运!

Playground 代码链接