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
相关产品推荐
相关产品推荐

