TypeScript合并多工具类/函数对象时如何保留类型与实例配置?
TypeScript 合并多个工具类实例并保留类型提示与私有配置
核心问题分析
你需要合并多个工具类实例,同时保留所有方法的类型智能提示,但遇到两个关键问题:
- 原始合并函数的泛型推断错误,返回类型为
Record<never, TUtilityFunction>; - 类中同名私有属性
config导致直接扩展实例时类型丢失,且需要保留各实例的配置上下文。
解决方案
通过自定义类型工具过滤方法属性、合并类型,并在实现中避免私有属性冲突,同时保留方法的原实例上下文。
1. 定义类型工具
首先创建几个类型工具来处理类型提取与合并:
// 提取对象中所有可枚举的方法属性(自动排除私有/受保护属性) type PickPublicMethods<T> = { [K in keyof T as T[K] extends Function ? K : never]: T[K] }; // 辅助类型:将联合类型转换为交叉类型,用于合并多个对象的方法类型 type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never; // 合并多个工具实例的方法类型为最终对象类型 type MergeUtilities<T extends Record<string, object>> = { [K in keyof UnionToIntersection<PickPublicMethods<T[keyof T]>>]: UnionToIntersection<PickPublicMethods<T[keyof T]>>[K] };
2. 实现合并函数
实现一个函数,只提取每个实例的方法属性进行合并,避开私有属性:
export const combineUtilities = <T extends Record<string, object>>(utilities: T): MergeUtilities<T> => { return Object.values(utilities).reduce((merged, utility) => { // 过滤出当前实例中的所有方法属性 const methods = Object.fromEntries( Object.entries(utility).filter(([_, value]) => typeof value === 'function') ); return { ...merged, ...methods }; }, {} as MergeUtilities<T>); };
3. 测试与验证
用你的实际类结构测试,确保类型提示和私有配置正常工作:
// 示例类型定义 type TSomeConfigType = { apiUrl: string }; type SomeCustomType = { id: number; name: string }; class UtilityA { private readonly config: TSomeConfigType; constructor(config: TSomeConfigType) { this.config = config; } DoSomeWork = (arg1: SomeCustomType, arg2: string): SomeCustomType => { console.log(this.config.apiUrl); // 仍能访问原实例的私有配置 return arg1; }; } class UtilityB { private readonly config: TSomeConfigType; constructor(config: TSomeConfigType) { this.config = config; } DoSomeOtherWork = (arg1: SomeCustomType, arg2: number): SomeCustomType => { console.log(this.config.apiUrl); // 仍能访问原实例的私有配置 return arg1; }; } // 使用合并函数 const utilA = new UtilityA({ apiUrl: 'https://a.example.com' }); const utilB = new UtilityB({ apiUrl: 'https://b.example.com' }); const merged = combineUtilities({ utilA, utilB }); // 此时merged会有完整的智能提示: // merged.DoSomeWork(arg1: SomeCustomType, arg2: string): SomeCustomType // merged.DoSomeOtherWork(arg1: SomeCustomType, arg2: number): SomeCustomType merged.DoSomeWork({ id: 1, name: 'test' }, 'foo'); merged.DoSomeOtherWork({ id: 2, name: 'test2' }, 123);
关键原理说明
- 类型过滤:
PickPublicMethods自动排除私有/受保护属性,因为这类属性在外部类型层面不可访问,不会出现在keyof T中。 - 类型合并:
UnionToIntersection将多个工具类的方法类型联合转为交叉类型,确保合并后的对象包含所有方法的准确类型。 - 上下文保留:类中的方法用箭头函数定义时,已经绑定了原实例的
this,因此合并到新对象后,方法仍能访问原实例的私有config,无需在合并对象中保留该属性。
内容的提问来源于stack exchange,提问作者NordicFinKoder
相关产品推荐
相关产品推荐

