如何泛型扩展函数参数的对象类型,添加任意名称的函数?
TypeScript 泛型扩展对象类型:添加任意名称函数的解决方案
需求说明
需要实现一个泛型方案,对任意传入的对象类型进行扩展:
- 允许在对象的任意层级添加任意名称的函数
- 新增函数接收所在层级的对象类型作为参数,并返回同类型
- 最终类型需保留原对象的所有属性,同时包含新增的函数
原代码问题分析
原代码的Expand和ExpandData类型逻辑存在缺陷:
- 错误地给非对象类型的属性添加了函数联合类型
- 无法支持任意名称的自定义函数键名,类型推导不符合预期
正确实现方案
方案1:保留函数的具体类型推导
如果希望函数参数和返回值的类型能被准确推导,使用以下实现:
// 给单个对象层级添加任意扩展函数的支持 type ObjectWithExtensibleFunctions<T> = T & { // 已存在的键保留原类型,新增键为接收当前层级对象并返回同类型的函数 [K: string]: K extends keyof T ? T[K] : (val: T) => T; }; // 递归处理嵌套对象,确保所有层级都支持扩展函数 type ExpandWithFunctions<T> = { [K in keyof T]: T[K] extends object ? ExpandWithFunctions<ObjectWithExtensibleFunctions<T[K]>> : T[K]; }; // 泛型create函数,约束输入为对象类型 export const create = <T extends object>(params: ExpandWithFunctions<T>): ExpandWithFunctions<T> => { return params; };
使用示例
type ICreate = { param: { first: { value: number; } } } const result = create<ICreate>({ param: { first: { value: 1, change: (val) => val, // val 自动推导为 { value: number } increment: (val) => ({ ...val, value: val.value + 1 }) } } });
此时result的类型为:
{ param: { first: { value: number; change: (val: { value: number; }) => { value: number; }; increment: (val: { value: number; }) => { value: number; }; }; }; }
方案2:将函数统一显示为Function类型
如果希望最终类型里的函数直接显示为Function(和你期望的结果一致),只需调整ObjectWithExtensibleFunctions的索引签名:
type ObjectWithExtensibleFunctions<T> = T & { [K: string]: K extends keyof T ? T[K] : Function; }; // 后续的ExpandWithFunctions和create函数保持不变
调整后result的类型会变为:
{ param: { first: { value: number; change: Function; increment: Function; }; }; }
实现逻辑说明
ObjectWithExtensibleFunctions<T>通过交叉类型结合原对象类型和自定义索引签名,既保留原属性的类型,又允许添加任意名称的函数ExpandWithFunctions<T>递归遍历对象的每个属性,对嵌套对象层级重复应用扩展逻辑,实现全层级支持create函数通过泛型约束确保输入为合法对象,同时保证参数和返回值的类型一致性
内容的提问来源于stack exchange,提问作者Vitaliy Severniy
相关产品推荐
相关产品推荐

