TypeScript如何推断多类组合的类返回类型并生成交叉类型
TypeScript 实现动态扩展类并正确推断返回类型
你的核心问题在于当前Compose函数的返回类型使用了未定义的typeof Base造成循环引用,且泛型处理没有正确提取扩展类的实例类型并交叉。要让TS正确识别所有扩展方法,需要调整Compose的类型定义,使其返回的构造函数实例类型包含所有扩展类的方法交叉。
步骤1:保留类型工具函数
首先保留UnionToIntersection(用于将联合类型转为交叉类型,合并所有扩展的方法):
export type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never;
步骤2:重构Compose函数的类型与实现
调整泛型定义,自动推断扩展类的类型,并让返回的构造函数实例类型为所有扩展类实例的交叉类型(如果需要基于已有基类扩展,可修改Composed的继承目标):
// 如果有基础核心类,可替换这里的空类 class CoreBase { baseMethod() { console.log("基础方法"); } } const Compose = <E extends new (...args: any[]) => any>( ...extensions: E[] ): new (...args: any[]) => CoreBase & UnionToIntersection<InstanceType<E>> => { // 创建继承基础类的临时类 class Composed extends CoreBase {} // 将所有扩展类的原型方法合并到临时类原型 extensions.forEach(extension => { Object.assign(Composed.prototype, extension.prototype); }); // 断言为目标类型,让TS识别合并后的方法 return Composed as new (...args: any[]) => CoreBase & UnionToIntersection<InstanceType<E>>; };
步骤3:使用Compose扩展Base类
现在定义你的扩展类,然后通过Compose合并,Base继承后就能自动识别所有扩展方法:
// 示例扩展类1 class Extension1 { extensionMethod1() { console.log("扩展方法1"); } } // 示例扩展类2 class Extension2 { extensionMethod2() { console.log("扩展方法2"); } } // 继承Compose合并后的类 class Base extends Compose(Extension1, Extension2) { customMethod() { this.baseMethod(); // 识别CoreBase的方法 this.extensionMethod1(); // 自动识别Extension1的方法 this.extensionMethod2(); // 自动识别Extension2的方法 } }
关键说明
- 用
InstanceType<E>提取每个扩展类的实例类型,再通过UnionToIntersection将联合类型转为交叉类型,确保所有扩展方法都能被TS识别。 - 避免了原代码中
typeof Base的循环引用问题,改为基于明确的基础类(或空类)+ 扩展交叉类型的返回定义。 - 无需手动传入泛型参数,TS会自动推断传入的扩展类类型。
内容的提问来源于stack exchange,提问作者Roberto Lonardi
相关产品推荐
相关产品推荐

