TypeScript中从子类集合实例化类并访问静态成员的方案
解决方案:定义可实例化且包含静态属性的构造函数类型
你的核心问题在于typeof A代表的是抽象类的构造函数类型,TypeScript会阻止你实例化抽象构造函数,即便实际传入的是子类。要同时满足访问静态属性和实例化的需求,你可以通过自定义构造函数类型来规避这个限制:
修正后的完整代码
abstract class A { s: string; n: number; static identifier: string; constructor(s: string, n: number) { this.s = s; this.n = n; } } class B extends A { static identifier: string = "B"; } class C extends A { static identifier: string = "C"; } // 定义同时满足:可实例化、带有identifier静态属性的构造函数类型 type ConcreteAConstructor = { new (s: string, n: number): A; identifier: string; }; function identifyAndInstantiate(identifier: string, classes: ConcreteAConstructor[]) { const identifiedClass = classes.find(candidate => candidate.identifier === identifier); if (!identifiedClass) return; // 现在可正常实例化,无类型错误 const instance = new identifiedClass("foo", 12); console.log(instance); } const classes: ConcreteAConstructor[] = [B, C]; identifyAndInstantiate("B", classes);
关键逻辑说明
自定义构造函数类型:
ConcreteAConstructor明确描述了两个核心要求:- 可以通过
new关键字创建A的实例(排除抽象构造函数的限制) - 必须带有
identifier静态属性(保证能访问子类的静态标识)
- 可以通过
类型适配优化(可选):
如果想让类型自动适配A的构造函数参数变化,可以用ConstructorParameters工具类型提取参数:type AConstructorArgs = ConstructorParameters<typeof A>; type ConcreteAConstructor = { new (...args: AConstructorArgs): A; identifier: string; };这样当A的构造函数参数修改时,不需要手动更新
ConcreteAConstructor的定义。约束子类实现静态属性(可选):
若要强制所有子类必须实现identifier,可以结合接口进一步约束:interface AStatic { identifier: string; } type ConcreteAConstructor = typeof A extends abstract new (...args: infer Args) => infer Instance ? (new (...args: Args) => Instance) & AStatic : never;
内容的提问来源于stack exchange,提问作者TheMatter1999
相关产品推荐
相关产品推荐

