-
Notifications
You must be signed in to change notification settings - Fork 13k
Description
I doubt this is expected behaviour, but it might be that I'm missing something.
Code
Doing this:
interface One {
one: string;
}
interface Two {
two: string;
}
type Three = One | Two;
const what1: Three = { one: 'ok' };
const what2: Three = { two: 'ok' };
const good1 = what1.one;
const good2 = what2.two;
good1
& good2
are good.
But adding a property to One:
interface One {
one: string;
extra: number; // <-- New line
}
interface Two {
two: string;
}
type Three = One | Two;
const what1: Three = { one: 'ok' }; // Error
const what2: Three = { two: 'ok' };
const good1 = what1.one; // Error
const good2 = what2.two;
Typescript will warn about both what1
and what1.one
, respectively:
TS2322: Type '{ one: string; }' is not assignable to type 'Three'.
Type '{ one: string; }' is not assignable to type 'Two'.
Property 'two' is missing in type '{ one: string; }'.
So instead of error for missing extra
prop, it will error for it missing a type from a seemingly arbitrary type.
and
TS2339: Property 'one' does not exist on type 'Three'.
Property 'one' does not exist on type 'Two'.
Here it looks like ts has coerced/figured out the type already.
Playground Link:
Just uncomment the line here
Trying to align them doesn't help:
When I add the extra
property to the second type
What fixes these issues is when I change it into an optional extra?: string
: here
Expected behavior:
I would have expected it to behave like logical or, but adding new properties seems to break the union.
Invalid, but maybe something like this: type Three = One? | Two?;
is what I actually expected?
I expected no error.
Actual behavior:
The union seems to behave as &
.
If I do foo: string | number
, I expect foo
to accept either type.
My guess is that with non-primitive types it doesn't work like that, since I couldn't literally merge an object
with a boolean
, so it merges the two interfaces, but somehow both are being reverse hypocritical, as in either are complaining about something the other is missing, while they have it themselves. And the order doesn't matter either, so they will always be incompatible whatever you try.
But that doesn't explain why it would work without the extra property, but different properties.
Related Issues:
#23031 The title seems to match my issue, but the errors are different. Although I have to say I've had that error before in relation to using two interfaces in union.
Search Terms:
type interfaces union