TypeScript中能否创建根据键类型返回不同值类型的Map
问题解答
可以实现。TypeScript原生Map的默认类型定义不支持按键的具体类型映射对应值类型,我们可以通过重写Map核心方法的类型签名,达到和你给出的Record示例完全一致的类型约束效果,且运行时和原生Map行为完全一致,无额外开销。
实现代码
首先定义基础类型和特殊键:
interface Section { variableName: string } interface Field { displayText: string } const specialKey = Symbol('This is the key to sections')
封装支持键值类型映射的自定义Map:
class TypedMap extends Map<symbol | string, Section | Field> { // 重写get方法的返回类型:根据传入键的类型匹配对应值类型 get<K extends symbol | string>(key: K): K extends typeof specialKey ? Section : K extends string ? Field : never { return super.get(key) as any } // 重写set方法的入参类型:根据传入键的类型约束传入值的类型 set<K extends symbol | string>(key: K, value: K extends typeof specialKey ? Section : K extends string ? Field : never ): this { super.set(key, value) return this } }
使用效果
const foo = new TypedMap() // 传入specialKey时,值必须符合Section结构,get返回值自动推导为Section类型 foo.set(specialKey, { variableName: 'heh' }) const section = foo.get(specialKey) section.variableName // 类型校验通过,无报错 // 传入普通字符串键时,值必须符合Field结构,get返回值自动推导为Field类型 foo.set('other', { displayText: 'sure' }) const field = foo.get('other') field.displayText // 类型校验通过,无报错 // 传值不符合键对应类型时会直接抛出类型错误 foo.set(specialKey, { displayText: 'mismatch' }) // 类型错误:specialKey不接受Field结构的值 foo.set('test', { variableName: 'mismatch' }) // 类型错误:字符串键不接受Section结构的值
扩展说明
- 如果需要新增更多特殊键映射,只需要在
get、set方法的条件类型分支中追加对应规则即可,支持任意类型的键(包括对象、数字等Map原生支持的键类型),扩展性强于普通对象Record实现。 - 如果不想封装子类,也可以通过方法重载给单个Map变量做类型约束,但维护性不如封装类的方案。
内容的提问来源于stack exchange,提问作者wegry
相关产品推荐
相关产品推荐

