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
为什么需要这样做?
key
在for...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 错误“元素隐式具有‘任何’类型,因为索引表达式不是‘数字’类型”