TypeScript泛型函数包装时类型推断为unknown的问题求助
高阶函数包装泛型函数时泛型被推断为unknown的原因与解决方法
问题原因
当泛型函数传入你编写的wrapper时,TypeScript会自动将泛型函数实例化为一个具体类型。由于没有明确指定泛型参数,它会选用最宽泛的unknown来填充泛型占位符。原wrapper的类型参数Callback捕获的是这个实例化后的函数类型(即(a: unknown) => unknown),而非原泛型函数本身的<T>(a: T) => T类型,因此包装后的函数参数和返回值都被推断为unknown。
解决方法
要让高阶函数支持泛型函数,核心是保留原函数的泛型参数特性,避免TypeScript提前实例化泛型。我们可以通过条件类型提取原泛型函数的参数与返回值的关联关系,让包装后的函数也保持泛型特性:
修改后的代码
// 定义包装后的函数类型,保留原函数的泛型特性 type WrappedFunction<Fn extends (...args: any[]) => any> = Fn extends <T>(...args: infer Args) => infer Ret ? <T>(...args: Args) => { val: Ret } | { val: null } : (...args: Parameters<Fn>) => { val: ReturnType<Fn> } | { val: null }; const wrapper = <Fn extends (...args: any[]) => any>(fn: Fn): WrappedFunction<Fn> => { return (...args: any[]) => { try { const val = fn(...args); return { val } as any; } catch { return { val: null } as any; } } as WrappedFunction<Fn>; }; // 测试普通函数(正常工作) const concreteFunction = (n: number) => n; const wrappedConcrete = wrapper(concreteFunction); // 推断类型:(n: number) => { val: number } | { val: null } // 测试泛型函数(现在正常保留泛型) const genericFunction: <T>(a: T) => T = (n) => n; const wrappedGeneric = wrapper(genericFunction); // 推断类型:<T>(a: T) => { val: T } | { val: null }
简化版实现
如果不需要复杂的条件分支,也可以直接让wrapper返回一个泛型函数,通过类型参数绑定原函数的参数与返回值:
const wrapper = <T extends any[], R>(fn: (...args: T) => R) => { return <U extends T>(...args: U) => { try { const val = fn(...args); return { val } as { val: R }; } catch { return { val: null }; } }; }; // 泛型函数测试 const wrappedGeneric = wrapper(genericFunction); // 推断类型:<T>(a: T) => { val: T } | { val: null }
内容的提问来源于stack exchange,提问作者moomoolive
相关产品推荐
相关产品推荐

