TL;DR:
type NonDistributive<T extends string> = { kind: T };type Distributive<T extends string> = { [K in T]: { kind: K } }[T];
type A = NonDistributive<'x' | 'y'>// ^? type A = { kind: 'x' | 'y' }
type B = Distributive<'x' | 'y'>// ^? type B = { kind: 'x' } | { kind: 'y' }
Given the following `Token` union
type Token = 'x' | 'y' | 'z'
Let's say you want to create a new shape from `Token` that's something like this:
type Discriminated = { kind: 'x' } | { kind: 'y' } | { kind: 'z' }
And you try the most obvious way
type Map<T extends Token> = { kind: T };
It won't work because it won't "distribute" Token members correctly.
It will create a single `{ kind: T }` with every T member:
type T = Map<Token>;// ^? type T = { kind: 'x' | 'y' | 'z' }
We will need to use distribute the union in a way each member is treated individually, like `K in T`:
type Map<T extends Token> = { [K in T]: { kind: K } }[T]type T = Map<Token>// ^? type T = { kind: 'x' } | { kind: 'y' } | { kind: 'z' }
Using conditional type (a single ternary T extends any) also does the distributive because the condition checks each member individually:
type Map<T extends Union> = T extends any ? { kind: T } : never;type T = Map<Token>;// ^? type T = { kind: 'x' } | { kind: 'y' } | { kind: 'z' }
In other words:
type Map<T extends Union> = { kind: T };// ^ this T is a whole union 'x' | 'y' | 'z'type Map<T extends Union> = T extends any ? { kind: T } : never;// ^ this T represents a single union member eg 'y'type Map<T extends Union> = { [P in T]: { kind: P } }[T]// ^ this P is a single union member of T eg 'y'