[英]Typescript element implicitly has type any with for...in loops
I have a JSON object imported from a JSON file (with resolveJsonModule: true
).我有一个从 JSON 文件导入的 JSON 对象(使用resolveJsonModule: true
)。 The object looks like this:该对象如下所示:
"myobject": {
"prop1": "foo",
"prop2": "bar"
}
and it's type therefore looks like this:因此它的类型如下所示:
myobject: { prop1: string, prop2: string }
That's very nice but when I try to use a for...in
loop,这很好,但是当我尝试使用for...in
循环时,
for (const key in myobject) {
console.log(myobject[key])
}
I get this error:我收到此错误:
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; }'.
I understand that this means the iterator key
is of type string
and not of type 'prop1' | 'prop2'
我知道这意味着迭代器key
的类型是string
而不是类型'prop1' | 'prop2'
'prop1' | 'prop2'
. 'prop1' | 'prop2'
。 But I don't understand why the iterator doesn't get this type because I'm explicitly iterating through the property names of myobject
.但我不明白为什么迭代器没有得到这种类型,因为我明确地遍历myobject
的属性名称。 Did I miss a tsconfig property that enables this behavior?我是否错过了启用此行为的 tsconfig 属性? I would like not to do this:我不想这样做:
for (const key in myobject) {
console.log(myobject[key as 'prop1' | 'prop2'])
}
Because:因为:
A better way to this is:一个更好的方法是:
for (const key in myobject) {
console.log(myobject[key as keyof typeof myobject])
}
In this way, it won't break when you add a property or rename it这样,在添加属性或重命名时不会中断
Three solutions for typing for...in
loops, I am aware of: for...in
循环中输入for...in
三种解决方案,我知道:
A type assertion will force key
type to be narrowed to myobject
keys: 类型断言将强制将key
类型缩小到myobject
键:
for (const key in myobject) {
console.log(myobject[key as keyof typeof myobject])
}
The key variable cannot be typed inside the for-in loop, instead we can declare it outside: key 变量不能在 for-in 循环内输入,我们可以在外面声明它:
let key: keyof typeof myobject // add this declaration
for (key in myobject) {
console.log(myobject[key]) // works
}
function foo<T>(t: T) {
for (const k in t) {
console.log(t[k]) // works
}
}
foo(myobject)
key
in a for...in
loop will by design default to type string
.在for...in
循环中的key
将默认为类型string
。 This is due to the structural type system of TypeScript: the exact properties' keys shape is only known at run-time, the compiler cannot statically analyze, what properties are present on the object at compile-time.这是由于 TypeScript 的结构类型系统:确切的属性键形状仅在运行时知道,编译器无法静态分析,在编译时对象上存在哪些属性。 A key
type narrowed to myobject
properties would make the for...in
loop an unsafe operation type-wise.缩小到myobject
属性的key
类型会使for...in
循环成为不安全的操作类型。
Note: Some linked resources discuss Object.keys
, for which the same argumentation holds.注意:一些链接资源讨论了Object.keys
,同样的论点也成立。
Why doesn't Object.keys
return a keyof type in TypeScript? 为什么Object.keys
在 TypeScript 中不返回 keyof 类型? - by Ryan Cavanaugh - 瑞安·卡瓦诺 (Ryan Cavanaugh)
Comment by Anders Hejlsberg in TypeScript#12253 - also mentions for...in
Anders Hejlsberg 在 TypeScript#12253 中的评论- 也提到for...in
TypeScript#32321 links to a multitude of duplicate issues TypeScript#32321链接到大量重复问题
Specific comment towards for...in
by Anders Hejlsberg: Anders Hejlsberg对for...in
的具体评论:
I have my doubts about this one.我对这个有疑问。 In
for (var k in x)
wherex
is of some typeT
, it is only safe to say thatk
is of typekeyof T
when the exact type ofx
isT
.在for (var k in x)
其中x
是某种类型的T
,也只是肯定地说,k
的类型是keyof T
时的确切类型x
是T
。 If the actual type ofx
is a subtype ofT
, as is permitted by our assignment compatibility rules, you will see values ink
that are not of typekeyof T
.如果x
的实际类型是T
的子类型,正如我们的赋值兼容性规则所允许的那样,您将看到k
中不是keyof T
类型的keyof T
。
if you want to have an object to be dynamic in the future create a model like this如果您希望将来有一个动态的对象,请创建这样的模型
interface PropertyItemModel {
propName: string;
propValue: string;
}
and in the component you can fetch data by loop在组件中,您可以通过循环获取数据
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}`)
});
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.