Im trying to understand why I get a compiler warning from Typescript when trying to create a new object based on an existing object of the same type.
In the code below you can see that spreading the key2
value causes the error Type 'string | undefined' is not assignable to type 'string'.
. Although key2
is optional, i'm spreading the value from object1
which we know has a key2
entry.
type Test = {
key1: string;
key2?: {
key3: string;
}
}
const object1:Test = {
key1: "hello",
key2: {
key3: "hi"
}
}
const object2:Test = {
...object1,
key2: { // error here
...object1.key2
}
}
Type error:
Type '{ key3?: string | undefined; }' is not assignable to type '{ key3: string; }'.
Types of property 'key3' are incompatible.
Type 'string | undefined' is not assignable to type 'string'.
Type 'undefined' is not assignable to type 'string'.(2322)
I'm just interested in understanding the behaviour here and the best way to handle this sort of situation.
Thanks
CodePudding user response:
The type of key2
is:
key2?: {
key3: string;
}
That means key2
is:
- allowed to be absent
- allowed to be
undefined
- allowed to be
{ key3: string }
(an object withkey3
property that is is a string.)
What's not allowed is an object that has an optional key3
property.
But if we look at the type of your spread:
const a = { ...object1.key2 }
// { key3?: string | undefined; }
That's not a valid assignment of the key2
property because if its an object it must also have a key3
property with a string
value.
To satisfy this interface, you need to prevent creating an object if key2
is undefined.
One way to do that would be:
const object2:Test = {
...object1,
key2: object1.key2 && {
...object1.key2
}
}