TypeScript泛型两次引用同一键实现Map键值类型约束
问题原因
原有写法中Map<keyof A, A[keyof A]>的两个泛型参数在声明阶段就被解析为互相独立的联合类型:
- 键类型被固定为
'a' | 'b' - 值类型被固定为
boolean | number
TypeScript 不会自动追踪两个联合类型成员之间的对应绑定关系,只要传入的键属于键联合、值属于值联合就会通过校验,因此会出现'a'键传入数字值不报错的漏检问题。
实现方案
通过自定义类型安全的Map类型,重写set、get方法的类型签名,让方法调用时根据传入的键动态推导对应的值类型,实现键值类型的强绑定:
type A = { a: boolean, b: number, }; type TypeSafeMap<T extends object> = Omit<Map<keyof T, T[keyof T]>, 'get' | 'set'> & { set<K extends keyof T>(key: K, value: T[K]): this; get<K extends keyof T>(key: K): T[K] | undefined; }; const myMap: TypeSafeMap<A> = new Map(); // 校验结果 myMap.set('a', 1); // 类型错误:number 不能赋值给类型 boolean myMap.set('a', true); // 校验通过 myMap.set('b', 1); // 校验通过
特性说明
- 完全复用原生
Map的运行时实现,无额外性能开销,仅在类型层面做增强 - 除
get、set外,has、delete、clear、forEach等原生Map方法均可正常使用,类型逻辑保持一致 - 工具类型通用,传入任意对象类型作为泛型参数,即可生成对应键值绑定关系的安全Map类型
内容的提问来源于stack exchange,提问作者Page not found
相关产品推荐
相关产品推荐

