You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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);

关键逻辑说明

  1. 自定义构造函数类型:
    ConcreteAConstructor明确描述了两个核心要求:

    • 可以通过new关键字创建A的实例(排除抽象构造函数的限制)
    • 必须带有identifier静态属性(保证能访问子类的静态标识)
  2. 类型适配优化(可选):
    如果想让类型自动适配A的构造函数参数变化,可以用ConstructorParameters工具类型提取参数:

    type AConstructorArgs = ConstructorParameters<typeof A>;
    type ConcreteAConstructor = {
        new (...args: AConstructorArgs): A;
        identifier: string;
    };
    

    这样当A的构造函数参数修改时,不需要手动更新ConcreteAConstructor的定义。

  3. 约束子类实现静态属性(可选):
    若要强制所有子类必须实现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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 01:55:11