by Gabriel Vergnaud @gvergnaud
Implement a type Distribute Unions
, that turns a type of data structure containing union types into a union of
all possible types of permitted data structures that don't contain any union. The data structure can be any
combination of objects and tuples on any level of nesting.
For example:
type T1 = DistributeUnions<[1 | 2, 'a' | 'b']>
// => [1, 'a'] | [2, 'a'] | [1, 'b'] | [2, 'b']
type T2 = DistributeUnions<{ type: 'a', value: number | string } | { type: 'b', value: boolean }>
// => | { type 'a', value: number }
// | { type 'a', value: string }
// | { type 'b', value: boolean }
type T3 = DistributeUnions<[{ value: 'a' | 'b' }, { x: { y: 2 | 3 } }] | 17>
// => | [{ value: 'a' }, { x: { y: 2 } }]
// | [{ value: 'a' }, { x: { y: 3 } }]
// | [{ value: 'b' }, { x: { y: 2 } }]
// | [{ value: 'b' }, { x: { y: 3 } }]
// | 17
For context, this type can be very useful if you want to exclude a case on deep data structures:
type ExcludeDeep<A, B> = Exclude<DistributeUnions<A>, B>
type T0 = ExcludeDeep<[{ value: 'a' | 'b' }, { x: { y: 2 | 3 } }] | 17, [{ value: 'a' }, any]>
// => | [{ value: 'b' }, { x: { y: 2 } }]
// | [{ value: 'b' }, { x: { y: 3 } }]
// | 17