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

How to represent the Type of any Subclass of an Abstract class in Typescript?

假设

abstract class A {};
class B extends A {};
class C extends A {};

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

function foo(Subclass: A){
   const obj = new Subclass();
}

这行不通。我收到错误

This expression is not constructable. Type 'BaseController' has no construct signatures.

然后我试了

function foo(Subclass: typeof A){   
   const obj = new Subclass();
}

现在我收到错误

Cannot create an instance of an abstract class.ts(2511)

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

可以实现吗?我如何让它工作?

为此,您需要通过构造函数引用来引用 class。

abstract class A {};
class B extends A {};
class C extends A {};

function foo(Subclass: new () => A) {   
   const obj = new Subclass();
}

在这种情况下,您可以将 BC 都传递给 foo,因为它们具有构造函数。 A 将不被接受,因为抽象 class 上没有构造函数。

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

function foo(subclass: new () => A) {
  const obj = new subclass();
}

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

foo(B); // okay
foo(C); // okay

它不会接受 A 本身,因为抽象 class 构造函数不被认为是 newable:

foo(A); // error, A is abstract

哦,作为为 Stack Overflow 问题制作示例 TypeScript 代码的人的注意事项:请注意 TypeScript 的类型系统是 structural. With the example definitions you gave, instances of A, B, and C are considered the same, empty type. And all objects are assignable to the empty type,所以这也有效:

foo(Date); // okay also

为防止这种情况,您应该在AB、and/or C中添加属性以在结构上区分它们,例如:

abstract class A {
  a = "A"
};
class B extends A {
  b = "B"
};
class C extends A {
  c = "C"
};

这将导致更多预期行为:

foo(B); // okay
foo(C); // okay
foo(A); // error, A is abstract
foo(Date); // error, 'a' is missing

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

Playground link to code