How to iterate over keys of a generic object in TypeScript?
Solution 1
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.
Solution 2
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...
}
Related videos on Youtube
Marcel
Updated on March 05, 2020Comments
-
Marcel about 4 years
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)?
-
Aleksey L. about 7 yearsYou can "type" your object as
any
or{ [index:string] : any }
-
Marcel about 7 yearsthanks 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 about 7 yearsthanks! :-) So it seems, the combination of my above approach with the definition of an indexable type (interface that defines index signature) is the way to go then...
-
Paleo about 7 years@Marcel Yes. You could just use an inline type definition:
let bigObject: {[index: string]: object} = {}
. It is the proposition of @Aleksey L., but withobject
instead ofany
. -
Marcel about 7 years@Paleo...yeah, true. in my case I am going to stick to an interface since I have multiple similar objects which will be processed together. thanks again!
-
Marcel about 7 yearsjust as an addition for anyone trying to do this as well: with TypeScript 2.2.2 the handling of string indexing for objects with index signatures has been simplified. so, now instead of writing bigObjectt[key] in the above examples, you can just write bigObject.key ! :-) here is a link to the relevant TypeScript blog post ... link
-
Paleo about 7 years@Marcel: Nope. If
key
is a variable that containsabc
,bigObject.key
will not access tobigObject.abc
. You have to keep the syntaxbigObject[key]
here. By the way, can you validate my answer?