如何实现TypeScript中基于Key确定返回类型的Map?
实现键关联类型的Map
可行,原生TypeScript Map因为是同构类型(所有键值对共享同一K/V类型),无法直接实现不同键对应不同返回类型,但可以通过封装泛型类来实现强类型关联的get/set方法。
问题根源
原代码中使用Map<indexType<any>, DataLoader<any, any>>,any导致TypeScript无法追踪具体键值对的类型映射,所以get返回any。
解决方案代码
1. 修正基础类型定义
declare class DataLoader<K, V> { constructor(/* ... */); // 保留原有DataLoader的方法定义 } // 目标对象类型 type Target<Entity> = { type: Entity; name: string; };
2. 封装带类型约束的Map子类
class TypedDataLoaderMap { // 内部用原生Map存储,类型放宽为unknown private innerMap = new Map<unknown, DataLoader<unknown, unknown>>(); /** * 存入键值对,键与值的类型强关联 * @param key 由Target对象和其属性键组成的数组 * @param value 对应属性类型的DataLoader实例 */ set<Entity, K extends keyof Target<Entity>>( key: [Target<Entity>, K], value: DataLoader<Target<Entity>[K], Target<Entity>[K]> ): void { this.innerMap.set(key, value); } /** * 获取对应键的值,返回类型自动匹配键的属性类型 * @param key 由Target对象和其属性键组成的数组 * @returns 对应类型的DataLoader实例或undefined */ get<Entity, K extends keyof Target<Entity>>( key: [Target<Entity>, K] ): DataLoader<Target<Entity>[K], Target<Entity>[K]> | undefined { // 通过类型断言将内部unknown转换为目标类型 return this.innerMap.get(key) as DataLoader<Target<Entity>[K], Target<Entity>[K]> | undefined; } }
3. 使用示例
const myMap = new TypedDataLoaderMap(); const thing: Target<string> = { type: 'pokemon', name: 'bla' }; const anotherThing: Target<number> = { type: 42, name: 'sheesh' }; // 存入时类型自动校验 myMap.set([thing, 'type'], new DataLoader<string, string>(/* ... */)); myMap.set([anotherThing, 'name'], new DataLoader<string, string>(/* ... */)); // 获取时自动推导返回类型 const res = myMap.get([thing, 'type']); // 类型:DataLoader<string, string> | undefined const res2 = myMap.get([anotherThing, 'name']); // 类型:DataLoader<string, string> | undefined
注意事项
- 数组作为Map键是引用类型,只有当get传入的数组和set时的数组是同一个引用时,才能获取到值。如果需要按值匹配键,需要额外实现自定义的键比较逻辑(比如将数组序列化为字符串作为键)。
- 封装类的泛型方法通过TypeScript的类型推导,确保了键和值的类型关联,避免了
any带来的类型丢失问题。
内容的提问来源于stack exchange,提问作者sev
相关产品推荐
相关产品推荐

