Why in the following code is Exclude<A,B>
resolving to the never
type? Can't the typescript compiler know (through static analysis) that A
and B
extend Parent
and thus Exclude<Choices, Parent>
should resolve to type C
?
interface Parent {}
interface A extends Parent {}
interface B extends Parent {}
interface C {}
type Choices = A | B | C
type Test = Exclude<Choices, Parent> // = type "never"???
const c: C = {}
const d: Test = c // Type 'C' is not assignable to type 'never'
I could hard code Parent = A | B
but I'm unsure why I need to.
This is because TypeScript has duck typing. Specifically, since C
and Parent
are the same interface, C
is assignable to Parent
.
Specifically, this compiles:
const c: C = {};
const p: Parent = c;
So, although C
doesn't explicitly extend Parent
, TypeScript still says that C
is a Parent
.
If you want this to work, just add something to Parent
that C
doesn't have.
interface Parent { foo: string }
interface A extends Parent {}
interface B extends Parent {}
interface C {}
type Choices = A | B | C
type Test = Exclude<Choices, Parent> // = type C
const c: C = {}
const d: Test = c // works!