Typescript 元素隐式地具有任何类型,带有 for...in 循环

Posted

技术标签:

【中文标题】Typescript 元素隐式地具有任何类型,带有 for...in 循环【英文标题】:Typescript element implicitly has type any with for...in loops 【发布时间】:2020-04-01 16:13:49 【问题描述】:

我有一个从 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'])

因为:

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

【问题讨论】:

由于这是一项您无法通过 for 循环访问它的项目,只需使用 myobject.prop1 获取价值 【参考方案1】:

更好的方法是:

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

这样,当你添加属性或重命名它时它不会中断

【讨论】:

【参考方案2】:

输入for...in循环的三种解决方案,我知道:

1。类型断言

type assertion 将强制将 key 类型缩小为 myobject 键:

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

Playground

2。显式声明关键变量

关键变量cannot be typed在for-in循环里面,我们可以在外面声明它:

let key: keyof typeof myobject // add this declaration
for (key in myobject)  
  console.log(myobject[key]) // works

Playground

3。泛型

function foo<T>(t: T) 
  for (const k in t) 
    console.log(t[k]) // works
  


foo(myobject)

Playground

为什么需要这样做?

keyfor...in 循环中将设计为default to type string。这是由于 TypeScript 的structural type system:确切的属性键形状仅在运行时知道,编译器无法静态分析,在编译时对象上存在哪些属性。将key 类型缩小为myobject 属性会使for...in 循环在类型方面成为不安全的操作。

更多信息

注意:一些链接资源讨论了Object.keys,同样的论点也成立。

Why doesn't Object.keys return a keyof type in TypeScript? - 作者:瑞安·卡瓦诺

Comment by Anders Hejlsberg in TypeScript#12253 - 还提到了for...in

TypeScript#32321 链接到大量重复问题

Specific comment towards for...in 来自 Anders Hejlsberg:

我对此表示怀疑。在for (var k in x) 中,其中x 属于某种类型T,只有当x 的确切类型是T 时,才能说k 属于keyof T 类型。如果x 的实际类型是T 的子类型,在我们的赋值兼容性规则允许的范围内,您将在k 中看到不属于keyof T 类型的值。

【讨论】:

【参考方案3】:

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

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`)
     );
  

【讨论】:

我明白你的意思,但我不想重建依赖于这个键值对象的整个基础架构 :) 我可能会在未来的项目中使用它

以上是关于Typescript 元素隐式地具有任何类型,带有 for...in 循环的主要内容,如果未能解决你的问题,请参考以下文章

TypeScript:元素隐式具有“任何”类型,因为“字符串”类型的表达式不能用于索引类型

TypeScript - 元素隐式具有“任何”类型,因为“字符串”类型的表达式不能用于索引类型

TypeScript - ts(7053):元素隐式具有“任何”类型,因为“字符串”类型的表达式不能用于索引

Object.keys 迭代导致 Typescript 错误“元素隐式具有‘任何’类型,因为索引表达式不是‘数字’类型”

元素隐式具有“任何”类型,因为“字符串”类型的表达式不能用于索引类型 React Typescript

映射打字稿参数:绑定元素“列”隐式具有“任何”类型