statement 1
type c = never extends never ? true : false // true
yup, as expected
statement 2
type d = never extends infer P ? P : false // never
P is never
as expected
statement 3
type g = (never extends infer P ? P : false) extends never ? true : false // true
this makes sense, because we know from statement 2 P is never
and from statement 1, never
extends never
is true, so it returns true
statement 4
type f = never extends infer P ? (P extends never ? true : false) : false // never, expecting true or at least false
this is totally unexpected, not only it did not returns true
, it also did not returns false
, but it returns never
which is not in the options
this is very confusing, WHY?
CodePudding user response:
Conditional types distribute over unions. Distribution is the process by which a conditional type is applied to each union constituent and the result of each application is unioned. Distribution happens only if the condition is applied over a naked type parameter.
// Is is distributive because we have `T extends` the condition is over just the type parameter
type Is<T> = T extends string ? "yes" : "no"
// Is is distributive we basically apply is to each constituent of string | number
type T0 = Is<string | number> // =Is<string> | Is<number> = "yes" | "no"
// No distribution
type T1 = string | number extends string ? "yes" : "no" // "no"
never
can be seen as the empty union, the union with no types. So when distributing over never
we actually don't apply the conditional type ever, resulting in never
regardless of the conditional type itself
// never => Is is never applied
type T2 = Is<never> // Distribute over nothing = never
If your case you introduce a new type parameter P
(with infer P
) and then create a distributive type (P extends never ? true : false
) over it. If P
is never
that conditional type is never applied, since you are distributing over the empty union and you get never