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

TypeScript中如何实现ES6 Map键值类型的关联约束?

TypeScript 实现ES6 Map的键值类型关联约束

原生Map的泛型参数K(键类型)和V(值类型)是独立的,不会做关联校验,所以直接写Map<string | number, number | string>会放行列如<number, number>、<string, string>的不合法组合,无法满足需求。可以通过重载Map核心方法的方式实现键值的关联约束,具体方案如下:

方案1:针对当前需求快速实现

// 定义Map的键值关联规则,同时重载set、get方法
interface RelatedMap extends Map<string | number, number | string> {
  set<T extends string | number>(key: T, value: T extends string ? number : string): this
  get(key: string): number | undefined
  get(key: number): string | undefined
}

// 实例化时断言为自定义的RelatedMap类型
const map = new Map() as RelatedMap

// 校验效果
map.set(1, 'a') // 正常通过
map.set('a', 1) // 正常通过
map.set(1, 1) // 类型报错:类型“number”的参数不能赋给类型“string”的参数
map.set('a', 'a') // 类型报错:类型“string”的参数不能赋给类型“number”的参数

// get方法也能自动推导返回值类型
const val1 = map.get(1) // 类型为:string | undefined
const val2 = map.get('a') // 类型为:number | undefined

方案2:通用可扩展的泛型实现

如果后续需要新增更多键值映射规则,可以使用通用泛型工具,适配任意关联规则:

// 通用Map约束泛型,泛型参数传入键值映射关系即可
type ConstrainedMap<T extends Record<any, any>> = {
  set<K extends keyof T>(key: K, value: T[K]): this
  get<K extends keyof T>(key: K): T[K] | undefined
  // 如果需要用到has、delete等其他Map方法,可按照相同规则补充重载
} & Omit<Map<keyof T, T[keyof T]>, 'set' | 'get'>

// 定义你的键值映射规则:key为string时value为number,key为number时value为string
type MyKVRule = {
  string: number
  number: string
}

// 实例化
const map = new Map() as ConstrainedMap<MyKVRule>

// 效果和方案1完全一致,需要新增规则时只需要修改MyKVRule即可

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 05:57:03