打字稿 - 没有带有“字符串”类型参数的索引签名

bru*_*ruh 5 javascript typescript reactjs

Javascript 中的事情很简单:

interface Person {
  id: number
  red: number
  green: number
  blue: number
  buckets: Array<BucketType>
  // Does the index signature go here? What does it look like?
  // I haven't seen any "standard" way of doing this
}

interface BucketType {
  color: string,
  weight: number
}

const personA = {
  id: 123,
  red: 4,
  green: 5,
  blue: 6,
  buckets: [
    {
      color: 'Blue',
      weight: 4
    }
  ]
}
const personB = {
  id: 456,
  red: 7,
  green: 8,
  blue: 9,
  buckets: [
    {
      color: 'Red',
      weight: 10
    }
  ]
}
const people = [ personA, personB ]

for (let person of people) {
  for (let bucket of person.buckets) {
    console.log(bucket.weight) // 4, then 10
    console.log(bucket.color)  // 'Blue', then 'Red'
    bucket.weight += person[bucket.color.toLowerCase()] // ERROR: NO INDEX SIGNATURE!!!! (Typescript)
    console.log(bucket.weight) // In pure Javascript, this logs '10', then '17'
  }

}
Run Code Online (Sandbox Code Playgroud)

老实说是什么鬼。如何为我的人物类型添加“索引签名”,以便我可以继续我的生活?

为文字上的抱怨而道歉,我只是因为在 TYPESCRIPT 方面取得进展而精疲力竭!!!

ted*_*ard 10

Typescript 类型检查器正在抱怨,因为它无法检查您的代码是否不会导致错误。Typescript 类型检查器无法读取字符串 'Red' 和 'Blue' 的值,并且知道如果它们是小写的,则它们与对象上的属性匹配。这只能在运行时完成,不能在类型检查时完成。

因此,您必须向编译器提示可能的结果bucket.color.toLowerCase()如下:

bucket.weight += person[bucket.color.toLowerCase() as 'red'|'blue'|'green'];
Run Code Online (Sandbox Code Playgroud)

  • 是否有速记或可重复使用的方式来指定此处的可能性?如果我有更多可能的选项,并且需要在代码中的多个位置使用它 - 多次写出列表似乎很愚蠢。 (2认同)
  • 我相信你可以做`type BucketColor = 'red' | '蓝色' | 'green'` 然后执行 `bucket.color.toLowerCase() as BucketColor` (2认同)