Typescript元素在循环中隐式地具有任何with for ...

时间:2019-12-08 09:14:46

标签: typescript for-in-loop object-property

我有一个从JSON文件(带有resolveJsonModule: true)导入的JSON对象。 该对象看起来像这样:

"myobject": {
  "prop1": "foo",
  "prop2": "bar"
}

,因此它的类型如下:

myobject: { prop1: string, prop2: string }

这很好,但是当我尝试使用for...in循环时,

for (const key in myobject)  {
  console.log(myobject[key])
}

我收到此错误:

TS7053: Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{ "prop1": string; "prop2": string; }'.
  No index signature with a parameter of type 'string' was found on type '{ "prop1": string; "prop2": string; }'.

我知道这意味着迭代器key的类型为string,而不是类型为'prop1' | 'prop2'。但是我不明白为什么迭代器没有得到这种类型,因为我明确地遍历了myobject的属性名。我是否错过了启用此行为的tsconfig属性? 我不想这样做:

for (const key in myobject)  {
  console.log(myobject[key as 'prop1' | 'prop2'])
}

因为:

  1. 我将来可能会添加新属性;和
  2. 这似乎有点作弊,我觉得有更好的方法可以做到这一点。

3 个答案:

答案 0 :(得分:1)

如果您希望将来有一个动态对象,请创建这样的模型

interface PropertyItemModel {
  propName: string;
  propValue: string;
}

,在该组件中,您可以循环获取数据

export class AppComponent {

  items: PropertyItemModel[] = [];

  constructor() {

    this.items = [
      { propName: "1", propValue: "foo" },
      { propName: "2", propValue: "bar" }]

     this.items.forEach(item => {
        console.log(`name: ${item.propName} - value: ${item.propValue}`)
     });
  }
}

答案 1 :(得分:1)

一种更好的方法是:

for (const key in myobject)  {
  console.log(myobject[key as keyof typeof myobject])
}

通过这种方式,添加属性或重命名它不会中断

答案 2 :(得分:0)

  

我不明白为什么迭代器没有得到这种类型,因为我明确地遍历了myobject的属性名称,

这是by design-在{。{1}}这样的for..in循环中,for (const key in myobject)的类型为key。编译器无法静态分析对象上确切具有的属性。属性键的确切形状仅在运行时才知道,因此他们决定将类型扩展为string以保持完整性(类似于Object.keys)。

唯一的例外是generic types

string

除了像Shalom Peles一样进行强制转换外,您还可以在规避之前声明function foo<T>(t: T) { for (const k in t) { k // Extract<keyof T, string> } } 类型,使其不能在循环本身中输入:

key

更多信息: