## Official Doc

When conditional types act on a generic type, they become distributive when given a union type.

Below is the official example.

``````type ToArray<Type> = Type extends any ? Type[] : never;
``````

`extends` is like a `if clause`, if `Type` is `string`, it would be:

``````type A = string extends any ? string[] : never;
``````

The `any` here is nothing special, we can use `unknown` or `{}` or `Object` as well to make it truthy.

``````type StrArrOrNumArr = ToArray<string | number>;
// string[] | number[]
``````

At first sight, above result might better be `Array<string | number>`, but becaue Conditional Type is Distributive, it works more like below

``````ToArray<A | B | C> = ToArray<A> | ToArray<B> | ToArray<C>;
``````

Above is what it means by Distributivity.

## More examples

I’ve put a playground to show how it works.

``````type StringNumber = string | number;
type B2 = StringNumber extends any ? StringNumber[] : never;
//   StringNumber[]
``````

Distributivity only works on generics. Above conditional type is not distributive.

``````type ToStringArray<Type> = Type extends string ? Type[] : never;
type B3 = ToStringArray<StringNumber>;
// string[]
``````

Above generic is distributive, so B3 is `ToStringArray<string> | ToStringArray<number>`, `ToStringArray<string> | never` so `string[]`.

``````type MyExclude<T, E> = T extends E ? never : T;
type C1 = MyExclude<string | number, number>;
//   string
``````

Now we can understand why `Exclude<T>` could be written with `extends`, because it is distributive.

``````type MyExcludeReversed<T, E> = E extends T ? never : E;
type C2 = MyExcludeReversed<number, string | number>;
//   string

type MyExclude2<T, E> = T extends E ? [T, E] : never;
type C3 = MyExclude2<number | string | boolean, number | string | bigint>;
// [string, string | number | bigint] | [number, string | number | bigint]
``````

We can see only `T` is distributive, not `E`, it depends on the position in `extends` not in the generic.

What if we want to it to be distributive on E as well?, Simple, put `E` before `extends`.

``````type MyExclude3<T, E> = T extends E ? (E extends any ? [T, E] : never) : never;
type C3 = MyExclude3<number | string | boolean, number | string | bigint>;

// [string, string] |
//  [never, number] |
//  [never, bigint] |
//  [never, string] |
//  [number, number]
``````

Huh? It doesn’s seem to be result I expect, let’s change it a little bit

``````type MyExclude4<T, E> = T extends any
? E extends any
? [T, E]
: [never]
: never;
type C3 = MyExclude4<number | string | boolean, number | string | bigint>;
// [string, string]  |
//  [string, number] |
//  [string, bigint] |
//  [number, string] |
//  [number, number] |
//  [number, bigint]
``````

This is more we wanted. Ok, let’s break down the previous snippet.

``````type C3 = MyExclude3<number | string | boolean, number | string | bigint>;
``````

So for the first extends, `T` is distributed, `boolean` is filtered out, so it is identical to

``````MyExclude3<number, number | string | bigint> |
MyExclude3<string, number | string | bigint>;
``````

Then `E` is distributed, notice that `T extends E` still needs to be satisfied, so

``````  [number, number] |
[never, string]  |
[never, bigint]  |
[never, number]  |
[string, string] |
[never, bigint]  |
``````

Remove the duplicate one and we get the previous result.

Awesome, now we truely understand the distributivity.