18
votes

I need to iterate over a large object which is just typed as "object". It contains an unknown number of objects of the same type.

In older posts I had found solutions using a generator within a custom Symbol.iterator function to make the large object iterable with a for..of loop.

But it seems to me, now in 2017, just using Object.keys is actually easier:

Object.keys(bigObject).forEach((key:string)=>{
console.log(bigObject[key]);
});

This actually runs just fine! But the TypeScript compiler keeps giving me the error "error TS7017: Element implicitly h as an 'any' type because type '{}' has no index signature"

Does anybody have an idea what I am missing here? Or what is the current best practice to do such an iteration with ES2015 and TypeScript (2.2.2)?

2
You can "type" your object as any or { [index:string] : any } - Aleksey L.
thanks a lot for the quick answer, Aleksey! Yeah, that gets rid of the error. But I am just wondering if this entire approach is what is considered best practice these days? Also with the "object" type just being introduced with TypeScript 2.2.2 I thought this was the way to go when dealing with an object of unknown type... - Marcel
This approach is perfectly valid. Regarding the error - it just says that the index has any type implicitly, but you have "noImplicitAny" compiler option enabled - Aleksey L.
Hint: try to understand what "index signature" means. - user663031

2 Answers

15
votes

for..in

When looking at the Typescript documentation (Typescript: Iterators and Generators), we see that the for..in syntax will iterate over the keys of the object.

for..in returns a list of keys on the object being iterated, whereas for..of returns a list of values of the numeric properties of the object being iterated.

We can use that to our advantage to index into our object and get the strongly typed value:

// 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...
}

Solution

We can use that to get an elegant solution to the question:

// 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...
}
12
votes

It contains an unknown number of objects of the same type.

Maybe with a generic interface BigObject<T> for your dictionary?

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

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

Here I wrote the type object in let bigObject: BigObject<object>. You can use a better type.