There is type definition in typescript:
type Exclude<T, U> = T extends U ? never : T;
We can use it to exclude a type from another type:
type AB = 'a' | 'b'
type AC = 'a' | 'c'
type X = Exclude<AB, AC>
The type X
is b
now.
But when I use the content of Exclude
directly:
type X = AB extends AC ? never : AC;
The type X
is different, it's not b
anymore, it's AC
.
I can't understand why it behaves differently.
Firstly if you replace the content, X
would be type X = AB extends AC ? never : AB;
. But that will not give you the same result either.
The reason is that conditional types have a special behavior when it comes to naked type parameters, they distribute over them if they are a union. So when you use Exclude
, each member of the union is separately put through the condition and the result is unioned. So Exclude<AC, AB>
is equivalent to:
type X = ('a' extends AC ? never : 'a') | ('b' extends AC ? never : 'b')
This distributive behavior does not occur with anything except naked type parameters (naked meaning T
is not used in another type, such as a tuple, an array or as a parameter to another generic type), this is why using the type directly in the condition does not yield the same result. You can read more here
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With