You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用相似对象属性值作为对象映射键时的隐式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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 07:35:20