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

TypeScript中如何用具体类型包装泛型函数的回调并实现正确类型推导

TypeScript中如何用具体类型包装泛型函数的回调并实现正确类型推导

看起来你想要实现一个包装函数,它能接收任意单参数泛型函数,调用时传入string类型的参数,并且正确推导该泛型函数在类型参数为string时的返回类型。我来帮你解决这个问题,先看最终的可行方案:

declare function generic1<T>(t: T): T;
declare function generic2<T>(t: T): { a: T };
declare function generic3<T>(t: T): { b: T[] };

// 正确的类型定义
function string_wrapper<F extends <T>(t: T) => any>(f: F): F extends <T>(t: T) => infer R ? R extends unknown ? R : never : never {
    return f('hi') as any;
}

const r1 = string_wrapper(generic1); // 类型:string ✅
const r2 = string_wrapper(generic2); // 类型:{ a: string } ✅
const r3 = string_wrapper(generic3); // 类型:{ b: string[] } ✅

方案细节解释

  1. 泛型约束F extends <T>(t: T) => any
    这里我们把F约束为泛型函数类型,确保传入的f是一个接受单个泛型参数T的函数,而不是已经被实例化为具体类型的函数。这一步是保留原函数泛型信息的关键。

  2. 返回类型的推断逻辑F extends <T>(t: T) => infer R ? R extends unknown ? R : never : never
    我们使用TypeScript的条件类型和infer关键字来提取:当泛型函数F的类型参数T被指定为string时,它的返回类型是什么。infer R会自动推断出F在T=string时的返回类型R,最终返回这个R。

  3. 类型断言as any
    由于TypeScript编译器暂时无法自动识别f('hi')的类型完全匹配我们推断出的R,所以需要一个类型断言来让编译器通过类型检查。这个断言是安全的,因为我们已经通过条件类型确保了f('hi')的类型就是我们需要的R。

更简洁的等价写法

我们也可以结合TypeScript内置的ReturnType工具类型来简化返回类型的定义,效果完全一致:

function string_wrapper<F extends <T>(t: T) => any>(f: F): ReturnType<(F extends { (t: string): infer R } ? F : never)> {
    return f('hi') as ReturnType<(F extends { (t: string): infer R } ? F : never)>;
}

为什么你之前的尝试不生效

  • 第一个尝试的泛型约束F extends <T>(t: T) => any方向是对的,但缺少基于infer的类型提取逻辑,无法正确推断T=string时的返回结果。
  • 后面将F约束为(t: string) => any的写法,会让TypeScript自动将传入的泛型函数实例化为具体的函数类型(比如generic1会被推断为(t: string) => string),虽然能得到正确的返回类型,但丢失了原函数的泛型信息,不符合你想要保留F作为泛型函数类型的核心需求。

备注:内容来源于stack exchange,提问作者Miguel Leon

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.15 09:37:59