扩展抽象类的类的类型是啥?

Posted

技术标签:

【中文标题】扩展抽象类的类的类型是啥?【英文标题】: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]?您还可以在尝试实例化这些给您错误的类的位置包含代码吗? 【参考方案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 实例,因为它共享完全相同的属性和方法。 看到这个问题***.com/questions/48829743/…【参考方案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()

【讨论】:

以上是关于扩展抽象类的类的类型是啥?的主要内容,如果未能解决你的问题,请参考以下文章

创建一个扩展抽象类的对象并将其添加到 Scala 中类型抽象类的序列中

Java 抽象类的理解

抽象类

如何对扩展/继承第 3 方类的类进行单元测试

接口与抽象类的区别

查看一个抽象类的方法是否未被其中一个扩展类覆盖的方法