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

如何使用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 00:45:05