如何初始化存储在抽象类变量中的类?

问题描述

我正在开发一个 TypeScript 项目是为了好玩,但遇到了一个有趣的情况,我无法实例化对类的引用,这可能是因为 TypeScript 假定它是一个类的实例

const programClass: Program = this.fetchProgram(programName) as Program

fetchProgram 正在从 map 返回一个 program 类,其中每个程序都是从文件动态加载的。

地图创建方式示例:

const programPath = "../../../programs"
const programFiles = fs.readdirsync(path.join(__dirname,programPath))

programFiles.forEach(file => {
  file = path.join(__dirname,programPath,file)
  const cmdClass = require(file).default
  const command = new cmdClass() as Program
  this.commands.set(command.alias,command)
})

每个“程序”都是一个导出类的文件,该类扩展了抽象类program

示例程序:

export default class ProgramEcho extends Program {
  alias = "echo"
  constructor(options: ProgramOptions) {
    super(options)
    console.log(`DEBUG: Program Instantiated: Echo`)
  }
}

现在, 回到第一个代码片段。这确实被视为 Program一个实例,当我真正需要它是扩展程序的某种类型的可构造类时。

const programClass: Program = this.fetchProgram(programName) as Program
const program = new programClass()

错误

const programClass: Program
This expression is not constructable.
  Type 'Program' has no construct signatures.ts(2351)

似乎你可以做一个简单的工厂模式,其中抽象类 program一个名为 create函数,它返回一个新的 Program,但你不能返回一个实例抽象类。

解决方法

正如您所观察到的,类型 Program 指的是 Program 类的一个实例。您想要的是一个可以创建 Program 实例的构造函数。假设您的所有 Program 子类都采用相同的构造函数参数,您想要的类型是:

type ProgramConstructor = new (options: ProgramOptions) => Program;

这允许您创建一个实例:

const programClass: ProgramConstructor = this.fetchProgram(programName) as ProgramConstructor;
const options: ProgramOptions = ??? // not sure where this comes from
const program = new programClass(options);

Typescript Playground Link