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

TypeScript中如何从派生类记录对象提取对应底层类类型?

TypeScript中为派生类记录对象成员推断正确类型的解决方案

你的问题出在build函数的泛型定义上——你用了统一的K类型约束所有工厂构造函数,导致TypeScript无法区分每个成员对应的具体派生类,最终所有ContractBuilder都被推断为父类factory的类型,丢失了各个子类的deploy方法签名信息。

要解决这个问题,需要让TypeScript为记录对象的每个键单独推断对应的工厂实例类型,具体修改如下:

abstract class factory {
    abstract deploy(...[]): any;
}

class a_factory extends factory {
    deploy = (a: number, b: string) => {};
}

class b_factory extends factory {
    deploy = (a: {}, b: number) => {};
}

const obj = {
    a: a_factory,
    b: b_factory
};

export type Object<F extends factory> = ReturnType<F['deploy']>;
export interface ContractBuilder<F extends factory> {
    deploy(...args: Parameters<F['deploy']>): Object<F>;
}
export type FactoryConstructor<F extends factory> = {
    new (): F;
};

const doSome = (any: any) => {};

// 修改泛型定义,不再用统一的K类型,保留每个属性的具体构造函数类型
const build = <F extends Record<string, FactoryConstructor<factory>>>(contracts: F) => {
    const a: { [contractName: string]: any } = {};

    for (const x in contracts) {
        a[x] = doSome(contracts[x] as any);
    }

    // 对每个键P,提取对应构造函数的实例类型
    type MySuperType = {
        [P in keyof F]: ContractBuilder<InstanceType<F[P]>>;
    };

    return a as MySuperType;
};

const MyTestObj = build(obj);

MyTestObj.a.deploy(1, "test"); // 现在会正确提示需要number和string类型参数
MyTestObj.b.deploy({}, 2);     // 正确提示需要object和number类型参数

关键改动说明:

  • 移除泛型参数K,让F直接表示包含具体工厂构造函数的记录类型,保留每个属性的原始类型信息。
  • 重新定义MySuperType时,使用InstanceType<F[P]>获取每个构造函数对应的实例类型,让每个ContractBuilder绑定到具体的派生类(如a_factory、b_factory),而非统一的父类factory。
  • 经过上述修改,TypeScript就能为每个成员的deploy方法推断出正确的参数和返回值类型。

内容的提问来源于stack exchange,提问作者sshmaxime

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 22:16:04