Reputation: 313
When I used Typescript and I got the error below.
I just wanted to loop an object and change values inside them.
But Typescript gave me the error even though it actually worked very well.
How can I remove the error from typescript in this script?
const info = {
id: "slkmd",
password: "asdfasdf!",
num: 1
}
const target = {
id: "asdf",
password: "asdf",
num: 21
}
Object.keys(info).forEach(key => {
info[key as keyof typeof info] = target[key as keyof typeof target]; // Error
// Type 'string | number' is not assignable to type 'never'.
// Type 'string' is not assignable to type 'never'
});
console.log(info);
Upvotes: 0
Views: 750
Reputation: 187124
Here keyof typeof info
is "id" | "password" | "num"
. It's one of those values but typescript doesn't know which one.
So when you do:
info[key] = target[key]
It's like doing:
info[key as "id" | "password" | "num"] = target[key as "id" | "password" | "num"]
See the problem? Typescript believes that, for example, it's possible for the first key
to be password
and the second key
to num
, which would be an invalid assignment. Typescript isn't quite smart enough to know that key
must be the same member of that union in each place, it only sees the type in each spot and makes the (correct) type error.
To fix it, the function must become generic.
const keys = Object.keys(info) as Array<keyof typeof info>
keys.forEach(<K extends keyof typeof info>(key: K) => {
info[key] = target[key];
});
Now the inner function has a generic parameter K
, which will be one specific key of info
, that is one specific member of that union.
The type of key in the function here is:
K extends "id" | "password" | "num"
Which means that it's a subtype of that union. And everywhere that type K is used will be the same subtype of that union for that invocation of the function.
And thus, the compiler's hunger is sated.
Upvotes: 2