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

如何使用infer推断泛型函数?重载函数泛型推断失效怎么解决?

TypeScript泛型函数类型处理的两个问题及解决方案

一、infer提取泛型函数类型时丢失泛型的原因及解决

问题根源

TypeScript中,当泛型函数类型被作为类型参数传入时,会被自动实例化为具体类型,而非保留泛型的模板结构。

你传入Fn<T>的<V>(v: V) => V,会被TypeScript视为一个能接受任意类型参数、返回对应类型的函数,最终退化成(param: unknown) => unknown。infer只能从具体的函数类型中提取参数和返回值,无法识别并保留原函数的泛型声明。

解决方案:用泛型高阶类型保留结构

要保留泛型函数的泛型特性,需要直接在类型定义中传递泛型参数,而非通过infer提取:

// 定义支持泛型传递的高阶类型
export type GenericFnWrapper = <V>(param: V) => V;

// 直接使用即可保留泛型结构:type F = <V>(param: V) => V
type F = GenericFnWrapper;

如果需要基于原泛型函数做类型转换,可以定义带泛型参数的高阶类型:

export type Fn<T> = <V extends T>(param: V) => V;

// F的类型为 <V extends unknown>(param: V) => V,即等价于<V>(param: V) => V
type F = Fn<unknown>;

二、重载函数传入后泛型推断失效的解决方法

问题根源

重载函数作为参数传递时,TypeScript只会使用最后一个重载(实现签名)进行类型推断,且外层函数fn的泛型参数P、R无法自动关联重载内部的<S>泛型,导致返回函数丢失泛型特性。

解决方案:让外层泛型与重载泛型绑定

调整fn的定义,使其泛型参数直接关联重载函数内部的泛型:

方法1:显式定义重载函数的泛型类型

// 定义带泛型的重载函数类型
type OverloadedGenericFn<S> = {
  (): "";
  (param: S): S;
};

// 让fn的泛型S与重载函数的泛型绑定
export function fn<S>(cb: OverloadedGenericFn<S>) {
  return (param: S, extra?: unknown) => {
    console.log(extra);
    return cb(param);
  };
}

// 现在f被推断为泛型函数:const f: <S>(param: S, extra?: unknown) => S
const f = fn({} as unknown as OverloadedGenericFn<any>);
const returned = f({ value: "value" as const }); 
// typeof returned 为 { value: "value" }

方法2:让fn直接接受泛型重载函数

export function fn<T>(cb: { (): ""; <U>(param: U): U }) {
  return <U>(param: U, extra?: unknown) => {
    console.log(extra);
    return cb(param);
  };
}

// f的类型为:const f: <U>(param: U, extra?: unknown) => U
const f = fn({} as unknown as { (): ""; <U>(param: U): U });
const returned = f({ value: "value" as const }); 
// typeof returned 为 { value: "value" }

核心是让外层函数的泛型参数与重载内部的泛型参数建立关联,确保TypeScript能正确推断返回函数的泛型结构。


内容的提问来源于stack exchange,提问作者Abdulramon jemil

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 16:04:55