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

TypeScript泛型函数:参数类型推断与可选参数默认值报错问题

问题

我想要编写一个泛型函数doThing<T, U extends T>(opts): U,其中类型U能从传入的opts参数中自动推断;核心要求是:如果未传入responseTransformer选项则使用默认值,此时T与U类型保持一致。

示例代码如下:

type Opts<Response, TransformedResponse extends Response> = {
  fetch: () => Response;
  responseTransformer?: (response: Response) => TransformedResponse;
};

function defaultResponseTransformer<Response> (response: Response): Response {
  return response;
}

function doApiFetch<Response, TransformedResponse extends Response>({
  fetch,
  responseTransformer = defaultResponseTransformer, // 理想情况:未指定responseTransformer时TransformedResponse推断为Response
}: Opts<Response, TransformedResponse>): TransformedResponse {
  return responseTransformer(fetch());
}

将defaultResponseTransformer作为默认值写在解构语句中时,出现错误提示:'TransformedResponse' could be instantiated with an arbitrary type which could be unrelated to 'Response'.


解决方案

方法1:使用函数重载

通过定义函数重载,明确区分「未提供转换器」和「提供转换器」两种调用场景,让TypeScript能精准推断类型:

type Opts<Response, TransformedResponse extends Response> = {
  fetch: () => Response;
  responseTransformer?: (response: Response) => TransformedResponse;
};

function defaultResponseTransformer<Response>(response: Response): Response {
  return response;
}

// 重载1:未传入responseTransformer时,返回类型与fetch的返回类型一致
function doApiFetch<Response>(opts: Omit<Opts<Response, Response>, 'responseTransformer'>): Response;
// 重载2:传入responseTransformer时,返回转换后的目标类型
function doApiFetch<Response, TransformedResponse extends Response>(opts: Opts<Response, TransformedResponse>): TransformedResponse;
// 函数实现
function doApiFetch<Response, TransformedResponse extends Response>({
  fetch,
  responseTransformer = defaultResponseTransformer,
}: Opts<Response, TransformedResponse>): TransformedResponse | Response {
  return responseTransformer(fetch());
}

方法2:调整泛型约束与默认值

给TransformedResponse设置默认类型为Response,同时通过类型断言让默认值的类型与泛型匹配,解决类型不兼容问题:

type Opts<Response, TransformedResponse extends Response = Response> = {
  fetch: () => Response;
  responseTransformer?: ((response: Response) => TransformedResponse) | undefined;
};

function defaultResponseTransformer<Response>(response: Response): Response {
  return response;
}

function doApiFetch<Response, TransformedResponse extends Response = Response>({
  fetch,
  responseTransformer = defaultResponseTransformer as (response: Response) => TransformedResponse,
}: Opts<Response, TransformedResponse>): TransformedResponse {
  return responseTransformer(fetch());
}

错误原因说明

原代码报错是因为:当未传入responseTransformer时,TypeScript无法确定TransformedResponse的具体类型——它可能被推断为任意继承自Response的类型,但默认值defaultResponseTransformer的类型是(response: Response) => Response,和不确定的TransformedResponse无法兼容,因此抛出类型不匹配的错误。


内容的提问来源于stack exchange,提问作者Trevor Dixon

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 17:45:56