Freewind
Freewind

Reputation: 198328

Can't understand `Exclude<T, U>` in typescript correctly

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.

Upvotes: 4

Views: 152

Answers (1)

Titian Cernicova-Dragomir
Titian Cernicova-Dragomir

Reputation: 250136

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

Upvotes: 7

Related Questions