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方法类型的映射:
- 定义首字母大写的API映射类型:
type APICapitalized = { [K in keyof API as Capitalize<K>]: API[K] };
- 修改
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
相关产品推荐
相关产品推荐

