You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.10 04:12:03