Consider the following use of extends
to remove members from a union type:
type RemoveNames<N, K> = N extends K ? never : N
type Names = 'bill' | 'jane' | 'freddy'
type Bill = RemoveNames<Names, 'jane' | 'freddy'> // type Bill = 'bill'
In a related question, N extends K
was defined to mean that "N is assignable to K", but in this case (on the face of it) N
is not assignable to K
- only a narrowed version of N
is assignable to K
.
How to interpret extends
in this case? Are the members of N
iterated over and "filtered" (?) if they're not in K
?
CodePudding user response:
When resolving the Bill
type, TypeScript takes every type of the Names
union type and resolves the conditional type N extends K ? never : N
, then builds a final union type with the results:
- Does
'bill'
extend'jane' | 'freddy'
? No:N extends K ? never : N
gives'bill'
- Does
'jane'
extend'jane' | 'freddy'
? Yes:N extends K ? never : N
givesnever
- Does
'freddy'
extend'jane' | 'freddy'
? Yes:N extends K ? never : N
givesnever
The final type is the union of these three types 'bill' | never | never
which gives 'bill'
.
This behavior is described in the Distributive Conditional Types chapter of the docs.