如何在TypeScript中为Map定义类似Bar的结构化类型?
如何为TypeScript中的Map定义结构化类型?
在TypeScript中,我们可以轻松定义数组类型:
type Foo = string[];
如果需要建模更具结构化的类对象数据,还可以用这种方式:
type Bar = [[name: string], [age: number], [consent: boolean]];
但标准库中Map<K, V>的泛型定义是统一键类型和值类型的,没法像上面的Bar那样体现每个键对应特定值类型的结构。那怎么给Map定义这种结构化类型,让编译器能准确推断每个键返回的值类型?
比如下面的示例,我们希望map1.get("name")能被推断为string类型:
const map1 = new Map(); map1.set("name", 'bob'); map1.set("age", 102); map1.set("consent", true); // 期望此处类型被推断为string const shouldBeString = map1.get("name");
解决方案1:手动定义结构化Map类型
我们可以创建一个自定义类型,基于目标对象结构扩展Map,重载get和set方法来绑定键值类型:
// 定义结构化Map的通用类型 type StructuredMap<T extends Record<string, unknown>> = Map<keyof T, T[keyof T]> & { get<K extends keyof T>(key: K): T[K]; set<K extends keyof T>(key: K, value: T[K]): this; }; // 使用时指定目标结构 const map1: StructuredMap<{ name: string; age: number; consent: boolean }> = new Map(); map1.set("name", 'bob'); // 类型检查通过 map1.set("age", 102); map1.set("consent", true); const shouldBeString = map1.get("name"); // 类型自动推断为string
解决方案2:通过初始化条目自动推断类型
如果不想手动写结构类型,可以利用as const固定初始化条目的类型,再通过工具类型提取键值对应关系:
// 从条目数组生成结构化Map类型的工具 type StructuredMapFromEntries<T extends readonly [string, unknown][]> = Map< T[number][0], T[number][1] > & { get<K extends T[number][0]>(key: K): Extract<T[number], [K, unknown]>[1]; set<K extends T[number][0]>(key: K, value: Extract<T[number], [K, unknown]>[1]): this; }; // 用const断言固定条目类型 const entries = [ ["name", "bob"], ["age", 102], ["consent", true] ] as const; // 自动生成结构化Map类型 const map1: StructuredMapFromEntries<typeof entries> = new Map(entries); const shouldBeString = map1.get("name"); // 类型推断为string
这两种方式都能让Map拥有类似对象的结构化类型检查,确保每个键对应的值类型准确,同时保留Map的原生方法特性。
内容的提问来源于stack exchange,提问作者TrevTheDev
相关产品推荐
相关产品推荐

