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

TypeScript报错:值可能为undefined但类型未声明为undefined

TypeScript中Payload类型为何会出现undefined的类型推断问题?

代码示例

type ApiMethods = {
  getToken(args: { tokenAddress: string; tokenName: string }): string;
  getRank(): string;
  getName(): string;
};

type Payload<K extends keyof ApiMethods> = Parameters<
  ApiMethods[K]
>[0] extends undefined
  ? {}
  : Parameters<ApiMethods[K]>[0];

function buildUrl<M extends keyof ApiMethods>(
  payload: Payload<M>,
) {
  let keys = Object.keys(payload)
}

报错信息

No overload matches this call.
Overload 1 of 2, '(o: {}): string[]', gave the following error.
Argument of type '{} | { tokenAddress: 0x${string}; tokenName: string; } | undefined' is not assignable to parameter of type '{}'.

问题分析

你疑惑的是,明明已经在Payload类型中设置:当函数的第一个参数类型是undefined时返回空对象{},但TypeScript仍推断payload可能为undefined。

问题出在TypeScript对无参数函数的Parameters工具类型处理,以及泛型条件类型的推断逻辑:

  • 对于getRank、getName这类无参数函数,Parameters<ApiMethods[K]>返回的是空元组[],而非包含undefined的元组。此时Parameters<ApiMethods[K]>[0]的类型是never,而非undefined。
  • 虽然never extends undefined的结果为true,理论上Payload<K>应返回{},但在泛型函数buildUrl中,TypeScript无法准确解析这个条件类型的结果,错误地将undefined纳入了payload的联合类型。

解决方案

调整Payload类型的判断逻辑,直接检查函数参数元组是否为空,而非依赖Parameters[0] extends undefined:

type ApiMethods = {
  getToken(args: { tokenAddress: string; tokenName: string }): string;
  getRank(): string;
  getName(): string;
};

// 修改后的Payload类型:直接判断参数元组是否为空
type Payload<K extends keyof ApiMethods> = Parameters<ApiMethods[K]> extends []
  ? {}
  : Parameters<ApiMethods[K]>[0];

function buildUrl<M extends keyof ApiMethods>(
  payload: Payload<M>,
) {
  let keys = Object.keys(payload) // 不再报错
}

这种方式能准确识别无参数函数的场景,将Payload<'getRank'>和Payload<'getName'>正确推断为{},payload的类型会被收窄为{} | { tokenAddress: string; tokenName: string },不再包含undefined,Object.keys调用自然正常。

内容的提问来源于stack exchange,提问作者Riccardo Perego

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 12:54:55