如何在TypeScript中遍历通用对象的键?

Mar*_*cel 7 typescript ecmascript-6

我需要遍历刚刚键入为“对象”的大对象。它包含未知数量的相同类型的对象。

在较早的文章中,我发现了使用自定义Symbol.iterator函数中的生成器的解决方案,以使大型对象可以通过for..of循环进行迭代。

但是在我看来,现在是2017年,仅使用Object.keys实际上更容易:

Object.keys(bigObject).forEach((key:string)=>{
console.log(bigObject[key]);
});
Run Code Online (Sandbox Code Playgroud)

这实际上运行得很好!但是TypeScript编译器不断给我错误“错误TS7017:元素隐式将h表示为'any'类型,因为类型'{}'没有索引签名”

有人知道我在这里缺少什么吗?或当前使用ES2015和TypeScript(2.2.2)进行迭代的最佳实践是什么?

Hay*_*der 26

经过一段时间的研究,我找到了一个让 TS 编译器满意的解决方案。在 for 循环之外声明键:

type TObj = { 
  key1: string; 
  key2: string 
}

const obj: TObj = {
  key1: "foo",
  key2: "bar"
};

// Declare the key outside the for loop
let t: keyof TObj;

for(t in obj) {
  obj[t]; // no compiler error
}
Run Code Online (Sandbox Code Playgroud)


Luk*_*ski 13

对于..in

在查看 Typescript 文档(Typescript: Iterators and Generators)时,我们看到 for..in 语法将迭代对象的

for..in 返回被迭代对象的键列表,而 for..of 返回被迭代对象的数值属性的值列表。

我们可以利用它来索引我们的对象并获得强类型值:

// Go through each key of the indexed object:
for (const key in indexedObject)
{
   // Get the indexed item by the key:
   const indexedItem = indexedObject[key];
   // Now we have the item.

   // Use it...
}
Run Code Online (Sandbox Code Playgroud)

解决方案

我们可以使用它来为这个问题提供一个优雅的解决方案:

// Go through each key in the bigObject:
for (const key in bigObject)
{
   // Get the strongly typed value with this name:
   const value = bigObject[key];
   // Now we have the the strongly typed value for this key (depending on how bigObject was typed in the first place).

   // Do something interesting with the property of bigObject...
}
Run Code Online (Sandbox Code Playgroud)

  • 当我这样做时,我仍然遇到这个问题。`元素隐式具有“any”类型,因为“string”类型的表达式不能用于索引类型“CustomList”。在“CustomList”类型上找不到带有“string”类型参数的索引签名。 (17认同)
  • 有没有一种方法可以内联执行此操作,例如“Object.keys”之类的方法,它返回也使用“in”迭代的键?(正确输入) (4认同)

Chr*_*son 8

简短的解决方案

对于那些喜欢节省打字时间并避免隐式任何错误和“for...in 语句的左侧必须是字符串”错误的人来说,这是我所知道的迭代 an 属性的最短方法。 Typescript 中的对象。注意没有接口或类。

export const collection = {property1: "", property2: ""};

let key: keyof typeof collection;
for (key in collection) collection[key] = key; // or other operation
Run Code Online (Sandbox Code Playgroud)

在这里,我们将属性的所有右侧分配为其键名称的某个函数——在本例中为“identity”。编译应该tsc没有错误。

回答原发帖者的问题

如果您有类而不是对象文字,则可以使用keyof后跟类名。如果您有一些对象具有未知的键,正如原始海报所询问的那样,您可以尝试内联类型(请参见下面的第一行):

export const collection: { [key: string]: any } = // inline type
  { Property1: "", Property2: "" }; // value could come from any source

let key: keyof typeof collection;
for (key in collection) collection[key] = key; // or other operation
Run Code Online (Sandbox Code Playgroud)


Pal*_*leo 6

它包含未知数量的相同类型的对象。

也许您的字典具有通用接口?BigObject<T>

interface BigObject<T> {
    [index: string]: T
}

let bigObject: BigObject<object> = {}
Object.keys(bigObject).forEach(key => {
  console.log(bigObject[key])
})
Run Code Online (Sandbox Code Playgroud)

在这里,我写的类型objectlet bigObject: BigObject<object>。您可以使用更好的类型。