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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 11:01:00