如何使用TypeScript泛型实现键值间接映射的正确类型匹配
mapTyped 多映射规则类型推导修复方案
核心思路
通过逐键映射的泛型推导替代统一的联合类型返回,为每个映射规则的键单独匹配Repository中对应方法的独有类型,避免所有方法类型合并。
修复后的完整类型定义
// 泛型约束: // Repo: 原始Repository的类型,约束为值是函数的对象 // M: 传入的映射规则,约束为值必须是Repo的合法键,自动拦截拼写错误 function mapTyped< Repo extends Record<string, (...args: any[]) => any>, M extends Record<string, keyof Repo> >(repo: Repo, mappings: M): { [K in keyof M]: Repo[M[K]] } { // 运行时实现和原有逻辑保持一致即可,不需要修改 return Object.fromEntries( Object.entries(mappings).map(([mapKey, repoMethodName]) => [mapKey, repo[repoMethodName]]) ) as any }
使用验证示例
// 示例:原始Repository的类型定义 type UserRepo = { getById: (id: number) => Promise<{ id: number; name: string }> listByName: (name: string) => Promise<{ id: number; name: string }[]> updateInfo: (id: number, data: { name?: string }) => Promise<boolean> } // 假设这是外部引入的JS版mapper实例 const userRepo: UserRepo = {} as any // 传入多条映射规则 const mappedApi = mapTyped(userRepo, { fetchUser: 'getById', searchUser: 'listByName', modifyUser: 'updateInfo' }) // 类型推导验证:每个方法都为独有类型,不会合并为联合 // mappedApi.fetchUser: (id: number) => Promise<{ id: number; name: string }> // mappedApi.searchUser: (name: string) => Promise<{ id: number; name: string }[]> // mappedApi.modifyUser: (id: number, data: { name?: string }) => Promise<boolean>
原问题原因说明
之前的类型定义大概率是将返回值写为Record<keyof M, Repo[keyof Repo]>,这种写法会取Repo所有方法的联合类型作为所有键的共同类型,改成逐键映射的写法后,每个键会单独匹配对应映射指向的方法类型,从根源避免类型合并。
注意事项
- 不需要修改原有运行时代码,仅调整类型定义即可兼容所有已有逻辑
- 天然保留原有能力:自动校验Repository与映射规则的方法名匹配、拦截拼写错误的键名、单/多规则下都能正确推导参数与返回值类型
内容的提问来源于stack exchange,提问作者joakimriedel
相关产品推荐
相关产品推荐

