使用相似对象属性值作为对象映射键时的隐式any类型错误
适配新旧API响应格式的TypeScript类型问题
我正在修改代码以适配新的API响应格式,同时保持与旧格式的兼容性。两种响应结构相似,主要差异在于键名。我编写了一个通过新旧键名映射获取属性的简单函数getProperty,但遇到了TypeScript类型错误。
简化后的代码
type NewFormat = { foo: string; bar: number; } type OldFormat = { f: string; b: number; } const newData = { foo: "baz", bar: 12 } const oldData = { f: "qux", b: 17 } const barMap = { 12: "TWELVE", 17: "SEVENTEEN" } const shorthandPropertyMap: { [key in keyof NewFormat]: keyof OldFormat; } = { foo: "f", bar: "b" }; const getProperty = ( data: NewFormat | OldFormat, prop: keyof typeof shorthandPropertyMap ) => { return prop in data ? (data as NewFormat)[prop] : (data as OldFormat)[shorthandPropertyMap[prop]!]; }; console.log(barMap[getProperty(oldData, "bar")] === "SEVENTEEN") console.log(barMap[getProperty(newData, "bar") as keyof typeof barMap] === "TWELVE")
触发的错误
Element implicitly has an 'any' type because expression of type 'string | number' can't be used to index type '{ 12: string; 17: string; }'. No index signature with a parameter of type 'string' was found on type '{ 12: string; 17: string; }'.
第二个console.log用类型断言做了临时解决,但我希望优化getProperty函数本身,不需要额外断言。尝试过泛型但没成功。
解决方案
通过泛型约束和字面量类型断言,让getProperty的返回类型与传入的属性键精准关联,彻底解决类型错误:
type NewFormat = { foo: string; bar: number; } type OldFormat = { f: string; b: number; } const newData = { foo: "baz", bar: 12 } const oldData = { f: "qux", b: 17 } const barMap = { 12: "TWELVE", 17: "SEVENTEEN" } // 用const断言锁定映射的字面量类型,避免TS将值宽泛推断为keyof OldFormat const shorthandPropertyMap = { foo: "f", bar: "b" } as const; // 定义映射类型,关联新键名与对应属性的类型 type PropTypeMap = { [K in keyof typeof shorthandPropertyMap]: K extends keyof NewFormat ? NewFormat[K] : never; }; const getProperty = <K extends keyof typeof shorthandPropertyMap>( data: NewFormat | OldFormat, prop: K ): PropTypeMap[K] => { return (prop in data ? (data as NewFormat)[prop] : (data as OldFormat)[shorthandPropertyMap[prop]]) as PropTypeMap[K]; }; // 无需额外断言,类型完全匹配 console.log(barMap[getProperty(oldData, "bar")] === "SEVENTEEN") console.log(barMap[getProperty(newData, "bar")] === "TWELVE")
关键优化点
- 给
shorthandPropertyMap添加as const断言,让TS识别具体的键值对字面量,而非宽泛的类型。 - 定义
PropTypeMap,根据新键名映射到对应属性的类型,确保返回值类型精准。 - 用泛型
K约束传入的prop,让返回类型与prop强关联,避免联合类型导致的索引错误。
修改后,getProperty会根据传入的属性键自动推导正确的返回类型,比如传入"bar"时返回number,完美匹配barMap的索引类型。
内容的提问来源于stack exchange,提问作者Andy E
相关产品推荐
相关产品推荐

