So i was going through the documentation on typescript and am not able to get my head around this concept.
So the documentation states :-
In instantiations of a distributive conditional type T extends U ? X : Y
, references to T
within the conditional type are resolved to individual constituents of the union type (i.e. T
refers to the individual constituents after the conditional type is distributed over the union type). Furthermore, references to T
within X
have an additional type parameter constraint U
(i.e. T
is considered assignable to U
within X
).
I cannot understand the part T refers to the individual constituents after the conditional type is distributed over the union type
.
Can anyone please explain this to me. An example of the same would be highly appreciated, the one in the documentation is not very clear to me.
Hmm, I just read through the documentation and it makes sense to me... I don't know if I can explain it any better than that, but let's go through it. In what follows, and
...x...
, means "some expression in whichx
might appear".In this case, a type parameter means a generic type parameter, and a naked type parameter is a type expression where the type parameter appears alone and is not part of some more complex type expression. And the checked type is the type appearing before
extends
. Let's see some examples:type A<T> = string extends T ? "yes" : "no"
This is not a distributive conditional type. The checked type isstring
, which is not a generic type parameter.type B<T> = {x: T} extends {x: number} ? "yes" : "no"
This is not a distributive conditional type. The checked type is{x: T}
, which has the type parameterT
in it, but is not a naked type parameter.type C<T> = T extends string ? "yes" : "no"
This is a distributive conditional type; the checked type isT
, which is a naked generic type parameter.This is the essence of what a distributive property does. If you have a type alias
F<T>
defined to be a distributive conditional type, as in:Then
F<T>
will distribute over unions, meaning that for any typesA
andB
, the typeF<A | B>
will be equivalent to the typeF<A> | F<B>
This is the part that confused you, but it's just explaining how the distribution works. It's saying that to evaluate
F<A | B>
, you should evaluateF<A> | F<B>
. So forF<A>
, you takeF<T> = T extends ...T... ? ...T... : ...T...
and plug inA
forT
(to getA extends ...A... ? ...A... : ...A...
), and then plug inB
forT
(to getB extends ...B... ? ...B... : ...B...
), and then unite them.Let's go through a concrete example:
What is this:
Well, here's how not to do it:
I just plugged
"a" | "b" | 0 | true
intoT
without distributing, and that's wrong. Here's how to do it correctly:See, we took the "individual constituents of the union" and replaced
T
with each one of them in turn.Okay, I hope that makes more sense now. Good luck!