如何在TypeScript泛型函数中移除参数属性并保留泛型?
解决泛型函数参数移除属性同时保留泛型的问题
要实现既移除函数第一个参数的age属性,又保留原函数的泛型特性,关键是让func2返回的仍然是泛型函数类型,而不是丢失泛型参数的具体函数类型。
问题分析
你之前的func2返回的是一个已经确定参数和返回值的具体函数,没有保留原函数的泛型参数定义,所以调用newFunction时无法再传入泛型参数。
解决方案代码
我们可以通过约束func2的类型参数为泛型函数,并在返回类型中保留泛型参数来实现需求:
// 原泛型函数func1 declare function func1<T extends {}>(params: { age: number; something: T } & Record<string, any>): string; // 改造后的func2:保留原函数的泛型特性,同时移除第一个参数的age属性 declare function func2<F extends <T>(...args: any[]) => any>( cb: F ): <T>(params: Omit<Parameters<F>[0], 'age'>) => ReturnType<F>; // 使用示例 const newFunction = func2(func1); // 正常使用泛型,参数中不再允许age属性 newFunction<{ name: string }>({ something: { name: "测试" }, extraProp: 456 }); // 传入age会触发类型错误(符合预期) // newFunction<{ name: string }>({ something: { name: "测试" }, age: 20 });
更通用的版本(支持多泛型参数)
如果原函数有多个泛型参数,可以用类型推断infer来提取原函数的泛型参数和结构,适配更复杂的场景:
declare function func2<F extends (...args: any[]) => any>( cb: F ): F extends <T extends any[]>(...args: infer Args) => infer R ? <T extends any[]>(params: Omit<Args[0], 'age'>) => R : never; // 使用方式和之前一致 const newFunction = func2(func1); newFunction<{ name: string }>({ something: { name: "测试" } });
原理说明
- 我们将
func2的类型参数F约束为泛型函数类型(<T>(...) => ...),而不是普通的函数类型。 - 返回类型同样定义为泛型函数
<T>(...) => ...,这样就保留了原函数的泛型参数能力。 - 通过
Omit<Parameters<F>[0], 'age'>精准移除第一个参数中的age属性,同时保留其他参数结构和泛型关联。
内容的提问来源于stack exchange,提问作者Oki
相关产品推荐
相关产品推荐

