Reputation: 8531
I have object with interface and I would like to dynamically access values by property key.
const tmpUser: IUser = {
username: "test",
namespace: "test",
password: "test"
}
Object.keys(tmpUser).forEach(property=>{
// Error: Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'IUser'.
console.log(tmpUser[property]);
})
// works
console.log(tmpUser["username"]);
// works
const someKey = "username";
console.log(tmpUser[someKey]);
also tmpUser.hasOwnProperty(property)
doesn't help neither.
Upvotes: 0
Views: 3364
Reputation: 3488
Because Object.keys
does not allow use to pass a generic type, its return type is string[]
, if we want to have type [keyof IUser]
we can cast it
const keys: [keyof IUser] = Object.keys(tmpUser) as [keyof IUser]
keys.forEach((property)=>{
console.log(tmpUser[property]);
})
BUT: It's is unnecessary. If you want to get key and value of that key you can simply use
Object.entries(tmpUser).forEach(([key,value])=>{
})
Upvotes: 2
Reputation: 36219
Throwing another solution here, especially since I'm assuming you'll have some kind of a process
function that takes in an object and does something with it:
const process = <O extends { [key: string]: any }>(object: O) => {
Object
.keys(object)
.forEach(prop => {
// No longer complains
console.log(object[prop]);
});
}
process(tmpUser);
Upvotes: 0
Reputation: 2073
You can specify that the IUser
keys will be of type string
(or if you want e. g. string | number
):
interface IUser extends Record<string, any> {
username: string
namespace: string
password: string
}
Upvotes: 2