TypeScript自定义键映射报错,如何解决类型不兼容问题?
解决TypeScript自定义键映射访问对象属性的类型错误
问题根源
当前代码里,keyMap的类型被定义为{[key in kM]:keyof IObj},仅声明每个映射键对应IObj的任意属性键,但TypeScript无法关联kM的每个成员与IObj的具体属性类型,导致类型推断模糊:
- 读取
obj[keyMap["year"]]时,TypeScript只能推断出类型是string | number,无法确定它是具体的number类型,因此无法赋值给number类型变量。 - 赋值
obj[keyMap["name"]]时,TypeScript无法确定目标属性的具体类型,只能推断为never,导致字符串赋值报错。
解决步骤
方法1:用as const断言保留精确类型
这是最简洁的方案,通过as const告诉TypeScript将keyMap的属性值视为字面量类型,保留每个键与具体属性的关联:
interface IObj { value:string; value2:string; value3:number; } let obj={ value:"JS", value2:"www.google.com", value3:2018 } type kM = "name"|"website"|"year"; // as const断言让TypeScript保留精确的字面量类型 const keyMap = { name:"value", website:"value2", year:"value3" } as const; const year:number = obj[keyMap["year"]]; // 类型正确推断为number,不再报错 obj[keyMap["name"]] = "Javascript"; // TypeScript明确目标属性为string类型,赋值正常
方法2:手动定义精确的字面量类型
如果需要显式声明keyMap的类型,可以直接写出每个键对应的具体属性键,让TypeScript明确类型关联:
interface IObj { value:string; value2:string; value3:number; } let obj={ value:"JS", value2:"www.google.com", value3:2018 } type kM = "name"|"website"|"year"; // 显式定义每个映射键对应的具体属性键 const keyMap: { name: 'value', website: 'value2', year: 'value3' } = { name:"value", website:"value2", year:"value3" } const year:number = obj[keyMap["year"]]; // 类型推断正确 obj[keyMap["name"]] = "Javascript"; // 赋值类型匹配
方法3:泛型函数封装访问逻辑
如果需要频繁通过键映射访问/修改属性,可以封装泛型函数确保类型安全:
interface IObj { value:string; value2:string; value3:number; } let obj={ value:"JS", value2:"www.google.com", value3:2018 } const keyMap = { name:"value", website:"value2", year:"value3" } as const; // 泛型函数:根据映射键返回对应类型的属性值 function getValue<K extends keyof typeof keyMap>(key: K): IObj[typeof keyMap[K]] { return obj[keyMap[key]]; } // 泛型函数:给映射键对应的属性赋值 function setValue<K extends keyof typeof keyMap>(key: K, val: IObj[typeof keyMap[K]]) { obj[keyMap[key]] = val; } const year:number = getValue('year'); // 类型匹配 setValue('name', 'Javascript'); // 赋值类型正确
内容的提问来源于stack exchange,提问作者Perumal Samy S
相关产品推荐
相关产品推荐

