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

TypeScript动态函数重载:API转handle函数的类型适配问题

TypeScript首字母大写命名的handle函数参数类型推导问题

现有类型定义

type Item = { id: string };
type Config = { enabled: boolean };

type API = {
  getItems(): Promise<Item[]> | undefined,
  getItem(id: Item['id']): Promise<Item> | undefined,
  getConfig(): Promise<Config>,
  getConfigKey(key: keyof Config): Promise<Config[keyof Config]>,
};

期望的handle调用形式

希望通过首字母大写的方法名调用handle函数,同时保证参数和返回类型的正确性:

handle('GetItems', (event) => {
  return [{} as Item]; // 符合Item[]类型
});

handle('GetItem', (event, id) => { // id自动推导为Item['id']类型
  return { id } as Item;
});

handle('GetConfig', (event, item) => ({}) as Config); // 此处应报错,因getConfig无参数

当前实现及问题

当前实现的handle函数能正确推导返回类型,但参数类型存在异常:

function handle<T extends keyof API>(
  name: Capitalize<T>,
  handler: API[T] extends (...args: infer Args) => infer R
    ? (event: Event, ...args: Args) => R
    : never
): void {}

问题表现:

  • 无参的API方法(如getConfig)调用handle时,传入额外参数不会触发预期的类型错误
  • 有参的API方法(如getItem)对应的handle函数中,除event外的后续参数类型被推导为never
  • 若改用原API的小写开头键名,参数类型推导正常,但不符合首字母大写的命名要求

最简解决方法

核心问题是Capitalize<T>无法让TypeScript反向推导出原keyof API的类型,需先构造首字母大写键名到原API方法类型的映射:

  1. 定义首字母大写的API映射类型:
type APICapitalized = {
  [K in keyof API as Capitalize<K>]: API[K]
};
  1. 修改handle函数,基于新的映射类型推导:
function handle<T extends keyof APICapitalized>(
  name: T,
  handler: APICapitalized[T] extends (...args: infer Args) => infer R
    ? (event: Event, ...args: Args) => R
    : never
): void {}

此时再调用handle函数:

  • 有参方法的参数类型会被正确推导
  • 无参方法传入额外参数会触发类型错误
  • 同时满足首字母大写的命名要求

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 18:54:53