如何在泛型Map中实现键到值的类型级联?
将联合类型映射对象转为带精确类型推断的Map
要实现基于Map的精确类型推断,核心是重载Map的get方法,让它根据传入的具体键返回对应类型的值。以下是完整实现:
type Category = 'A' | 'B' | 'C'; interface DataRecord<TCategory extends string = string> { category: TCategory; data: Record<string, string>; } // 重载Map的get方法,实现精确类型推断 type DataRecordGroups = Map<Category, DataRecord<Category>[]> & { get<K extends Category>(key: K): DataRecord<K>[] | undefined; }; // 初始化Map,TypeScript会自动校验条目类型 const groups: DataRecordGroups = new Map([ ['A', [{ category: 'A', data: { id: 'a1' } }]], ['B', [{ category: 'B', data: { id: 'b1' } }]], ['C', [{ category: 'C', data: { id: 'c1' } }]] ]); // 验证类型推断效果 const groupA = groups.get('A'); // 类型:DataRecord<'A'>[] | undefined if (groupA) { const catA = groupA[0].category; // 类型:'A'(精确字面量类型) } const groupB = groups.get('B'); // 类型:DataRecord<'B'>[] | undefined if (groupB) { const catB = groupB[0].category; // 类型:'B'(精确字面量类型) }
原理说明
原生Map<Category, DataRecord<Category>[]>的get方法只能返回DataRecord<'A'|'B'|'C'>[] | undefined,无法区分不同键对应的具体类型。通过:
- 保留基础
Map的结构,确保可以使用所有Map原生方法 - 重载
get方法,引入泛型K extends Category,让方法根据传入的键K,精确返回DataRecord<K>[] | undefined
如果需要更严格的构造校验,可以先定义精确的条目类型联合,再约束Map的构造参数:
// 定义每个键值对的精确类型 type DataRecordEntry = { [K in Category]: [K, DataRecord<K>[]] }[Category]; // 同样重载get方法的Map类型 type DataRecordGroups = Map<Category, DataRecord<Category>[]> & { get<K extends Category>(key: K): DataRecord<K>[] | undefined; }; // 构造时传入的数组必须符合DataRecordEntry[]类型 const groups: DataRecordGroups = new Map<DataRecordEntry>([ ['A', [{ category: 'A', data: {} }]], // 如果传入['A', [{ category: 'B', data: {} }]]会直接报错 ]);
这样能确保初始化的Map条目完全符合类型要求,避免出现键值不匹配的情况。
内容的提问来源于stack exchange,提问作者Paya
相关产品推荐
相关产品推荐

