问题描述
我正在开发一个 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);