This is a result of applying a distributive conditional type to never
. If a distributive conditional type is applied to a union, the result will be a union of applying that conditional type to each constituent of the union:
type IfExtends<T> = T extends number ? "Y" : "N"
type A = IfExtends<number | string> // = IfExtends<number> | IfExtends<string> = "Y" | "N"
So what does this have to do with never
? We can get a hint if we try to union never
with any other type:
type X = never | number // just number, never is omitted
never
is the empty union, ie the union with no constituent. Adding it to any other union will make it melt away because of this.
Because it is the empty union, when distributing over it, the conditional type actually never get evaluated, since there are no constituents in the union to apply it to, and we just get never
regardless of any condition in the conditional type
Using the actual inlined version does not produce the same result as distributivity only happens over naked type parameters, T
is a naked type parameter, keyof empty
is not.
You can disable distributivity by encasing T
in a tuple type:
type IfExtends<T, B, Y, N> = [T] extends [B] ? Y : N
let a: IfExtends<keyof empty, never, number, string> /// also numberkeyof empty
CLICK HERE to find out more related problems solutions.