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)?
43 Answers
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... } 3It 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.
After playing with it a while I found a solution that makes the TS compiler happy. Declare the key outside the for loop:
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 errors) { errors[t]; // no compiler error }