17

In plain JavaScript we can iterate over object props and values like so:

const values = Object.keys(obj).map(key => obj[key]);

In TypeScript this syntax is wrong because the TS compiler is displaying the following message:

Element implicitly has an 'any' type because expression of type 'string' can't be used to index type Object.

Is there an alternative way not using Map<string, T> to do it and get the value of each key?

I encountered this problem while building an app using React and TS and I have in my state an object which I need to do something like this:

const stateJSX: HTMLParagraphElement[] = Object.keys(obj).map(key => <p>`${key}: ${obj[key]}`<p>);

4 Answers 4

14

Object.keys()

To use Object.keys(), (as indicated in the original question), you can add a typecast indicating that the object is an indexable type:

for (const key of Object.keys(obj)) {
  console.log(`${key}: ${(obj as {[key: string]: string})[key]}`);
}

Or use a typecast on the key:

for (const key of Object.keys(obj)) {
  console.log(`${key}: ${obj[key as keyof typeof obj]}`);
}

Object.entries()

Object.entries() may be used without map() as follows:

for (const [key, value] of Object.entries(obj)) {
    console.log(`${key}: ${value}`);
}
Sign up to request clarification or add additional context in comments.

Comments

8

You can easily use it with some help of keyof operator:

const test = <T extends Record<string, unknown>>(obj: T) => {
 return (Object.keys(obj) as Array<keyof T>).map(key => obj[key])
}

You should asure TS, that key variable could be used as index for obj argument

3 Comments

You may want to note that Object.keys() does not return Array<keyof T> automatically because it is not generally safe to do so
@jcalz , yes You are right. I have read related github issue. It is better to use with immutable objects. Btw, do you now the better way to use Object.keys with TS? I know, we can do it with typeguards inside map function, but I think it is a bit overhead
This is the only answer that actually discusses how to do this in TypeScript.
6

Use Object.entries to iterate over both the keys and the values:

Object.entries(obj).map(([key, value]) => `${key}: ${value}`)

Comments

4

Use Object.entries

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

1 Comment

This answer is really near to this and this

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.