【问题标题】:What is the type of a class that extends an abstract class?扩展抽象类的类的类型是什么?
【发布时间】:2021-08-20 03:19:42
【问题描述】:

我有一个抽象类,以及在数组中扩展它的类。我要输入什么数组?

abstract class AbstractClassToExtend {
    constructor() { console.log("hello") }
}

class One extends AbstractClassToExtend {}
class Two extends AbstractClassToExtend {}

const array = [One, Two] // what do i type this array?

我尝试过const array: typeof AbstractClassToExtend[] = [One, Two],但是在创建数组中某个类的实例时,

new array[0]()

它给出了一个错误:

error TS2511: Cannot create an instance of an abstract class.

我正在使用 Typescript 4.3.2。

【问题讨论】:

  • 您的意思是写const array: typeof AbstractClassToExtend[] = [One, Two]?您还可以在尝试实例化这些给您错误的类的位置包含代码吗?

标签: typescript


【解决方案1】:

您特别想实例化数组中的类型,所以我不确定您是否可以将数组键入为具有抽象类。

也许这并不像您希望的那样优雅,但您可以拥有一个其他人继承的具体基础实现:

abstract class AbstractClassToExtend { }

class BaseImplementation extends AbstractClassToExtend { }

class One extends BaseImplementation { }
class Two extends BaseImplementation { }

const array: (typeof BaseImplementation)[] = [One, Two]

const a: BaseImplementation = new array[0]();
const b: BaseImplementation = new array[1]();

另一种方法是拥有一个返回抽象类型实例的函数数组:

const functions: Array<() => AbstractClassToExtend> = [() => new One(), () => new Two()];

const c: AbstractClassToExtend = functions[0]();
const d: AbstractClassToExtend = functions[1]();

【讨论】:

  • 数组的类型只要求它的元素是具有零参数构造函数的类,而不是它们扩展BaseImplementation(我可以在数组中添加String和Number等类,其参数是可选的)。
  • @astroide 这是我的例子的问题,还是 TypeScript 如何与鸭子打字一起工作?
  • 是的,TypeScript 正在使用某种鸭子类型。更具体地说,如果Duck 是一个具有quack() 方法返回string 的类并且您有一个Duck 类型的变量,则可以将该变量分配给具有相同属性和方法的任何对象,例如{"quack":()=&gt;"quack"}。同样,如果你有一个type DuckLike = {quack: ()=&gt;string} 类型,你可以将DuckLike 类型的任何变量分配给Duck 实例,因为它共享完全相同的属性和方法。
【解决方案2】:

你可以使用联合类型:

const array: (One | Two)[] = [One, Two]

更多:Defining array with multiple types in TypeScript

【讨论】:

  • 当我添加更多类时,我不需要更新联合类型吗?
【解决方案3】:

我得到这个工作的方式与接受的答案略有不同,它可能适合一些创建BaseImplementation 并不理想的用例。

不是直接使用类构造函数,而是添加一个通用的静态方法来初始化抽象类。这允许您拥有一个可初始化的 this 类型。

abstract class AbstractClassToExtend {
  constructor() {
    console.log("hello")
  }

  static init<T extends AbstractClassToExtend >(this: new () => T) {
      return new this()
  }
}

然后将new () =&gt; AbstractClassToExtend 添加到数组项的类型中。这使得数组项与调用AbstractClassToExtend.init() 兼容。

const array: (typeof AbstractClassToExtend & (new () => AbstractClassToExtend))[] = [One, Two]

使用init方法创建实例,而不是new array[0]()

const array: (typeof AbstractClassToExtend & (new () => AbstractClassToExtend))[] = [One, Two]
const one: AbstractClassToExtend = array[0].init()
const two: AbstractClassToExtend = array[1].init()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-08-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-12
    • 1970-01-01
    相关资源
    最近更新 更多