TypeScript封装泛型函数的高阶函数如何保留原函数类型信息?
问题原因
你当前实现的withUndefined泛型参数是在调用withUndefined包裹函数时就完成推导固定的,而泛型函数的泛型参数是在实际调用函数时才动态确定的,因此包裹阶段TS无法预判后续调用时的泛型类型,只能推导为unknown,导致泛型信息丢失。
解决方案
TS 4.7及以上版本
TypeScript 4.7版本开始支持对高阶泛型函数的推导,你可以改写withUndefined实现如下,即可自动保留传入函数的泛型信息:
type WithUndefined<F extends (input: any, ...args: any[]) => any> = F extends (input: infer I, ...args: infer R) => infer O ? { (input: undefined, ...args: R): undefined; (input: I, ...args: R): O; (input: I | undefined, ...args: R): O | undefined; } : never; function withUndefined<F extends (input: any, ...args: any[]) => any>(func: F): WithUndefined<F> { return ((input: any, ...args: any[]) => { if (input === undefined) return undefined; return func(input, ...args); }) as WithUndefined<F>; }
测试效果
function filterOutUndefined<E>(array: (E | undefined)[]): E[] { return array.filter((value) => value !== undefined) as E[]; } const filterOutUndefined_ = withUndefined(filterOutUndefined); const x = filterOutUndefined(['a', 'b', 'c']); // 类型为 string[] const y = filterOutUndefined_(['a', 'b', 'c']); // 类型为 string[],泛型正常保留 const z = filterOutUndefined_(undefined); // 类型为 undefined,符合预期 const n = filterOutUndefined_([1, 2, undefined]); // 类型为 number[],泛型正常推导
TS 4.7以下版本
更低版本的TypeScript没有原生支持高阶泛型推导,你可以通过手动标注返回函数类型的方式解决:
const filterOutUndefined_ = withUndefined(filterOutUndefined) as <E>(array: (E | undefined)[] | undefined) => E[] | undefined;
内容的提问来源于stack exchange,提问作者Remirror
相关产品推荐
相关产品推荐

