Iterating using Object.keys doesn't work because Object.keys returns an array of strings, not a union of all the keys. This is by design and won't be changed.
Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'User'.
No index signature with a parameter of type 'string' was found on type 'User'.7053
Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'User'.
No index signature with a parameter of type 'string' was found on type 'User'. });}
Casting to keyof typeof in the right spot makes it work:
This means you can't use the key to access the value on the object:
constnameKey = keys[0];
const nameKey: string
user[nameKey];
Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{ name: string; age: number; }'.
No index signature with a parameter of type 'string' was found on type '{ name: string; age: number; }'.7053
Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{ name: string; age: number; }'.
No index signature with a parameter of type 'string' was found on type '{ name: string; age: number; }'.
There's a good reason that TypeScript returns an array of strings here. TypeScript object types are open-ended.
There are many situations where TS can't guarantee that the keys returned by Object.keys are actually on the object - so widening them to string is the only reasonable solution. Check out this issue for more details.
You'll also find this fails if you try to do a for...in loop. This is for the same reason - that key is inferred as a string, just like Object.keys.
functionprintUser(user: User) { for (constkey inuser) {console.log(user[key]);
Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'User'.
No index signature with a parameter of type 'string' was found on type 'User'.7053
Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'User'.
No index signature with a parameter of type 'string' was found on type 'User'. }}
But for many cases, you'll feel confident that you know EXACTLY what shape that object is.
This is perhaps the solution that's most prone to misuse - hiding the cast inside a function makes it more attractive and might lead to people using it without thinking.
My preferred solution? Usually, casting does the job perfectly well. It's simple and easy to understand - and is usually safe enough.
But if you like the look of the type predicate or generic solutions, go for it. The isKey function looks useful enough that I'll be stealing it for my next project.
Got any more questions? Found any more solutions? Let me know: