TypeScript: How to Iterate Over Object Properties

Say you have simple object like the following:

1
2
3
4
const obj = {
    foo: 'foo',
    bar: 10
}

If we wanted to iterate over that objet properties in JavaScript we could simply do the following:

1
2
3
for (const property in obj) {
    console.log(`${property}: ${obj[property]}`);
}

Unfortunately, in TypeScript that would give the following error.

Error
obj[property]: Element implicitly has an ‘any’ type because expression of type ‘string’ can’t be used to index type ‘{ foo: string; bar: string; }’.

Because of how structural typing works there is no guarantee that property is effectively in the type declaration, therefore the type checker gives us an error.

To have a deeper understanding of why this happens have a look at this article: Typescript: Understand structural typing.

There a couple of ways to overcome this problem.

Introduce a type declaration for property

A possible way to fix the error is to declare the possible values assignable to property.

We can achieve it using the keyof T operator which yields the type of permitted property names for T.

1
2
3
4
5
let property: keyof typeof obj; // Type is 'foo' | 'bar'

for (property in obj) {
    console.log(`${property}: ${obj[property]}`);
}

Introducing let property: keyof typeof obj; we are now specifying that property can only be either "foo" or "bar". As a result, using the expression obj[property] will no longer produce errors.

Use Object.entries()

Object.entries() creates an array of tuples (key and value) that we can iterate over through a simple forEach() loop.

1
2
Object.entries(obj)
    .forEach(([key, value]) => console.log(`${key}: ${value}`))

Which one is better?

Both are suitable solutions but generally speaking keyof T is good for constants or in situations where you know the object won’t have additional keys and you want precise keys.

Object.entries() is more generally appropriate, especially if you prefer declarative over imperative programming style.