typescript Feb 19, 2026
Union to Intersection
Merge a union of object types into a single composite type.
UnionToIntersection collapses A | B | C into A & B & C. I reach for it when merging handler maps, plugin interfaces, or mixin types that are collected as a union but need to be consumed as a single composite object.
Type
union-to-intersection.ts
type UnionToIntersection<U> =
(U extends unknown ? (arg: U) => void : never) extends (arg: infer I) => void
? I
: never
type Handlers =
| { onClick: () => void }
| { onKey: (key: string) => void }
type Combined = UnionToIntersection<Handlers>
// Combined is { onClick: () => void } & { onKey: (key: string) => void } How it works
- The distributive conditional (
U extends unknown ? ... : never) wraps each union member into a function parameter position:(arg: A) => void | (arg: B) => void. - Contravariant inference does the heavy lifting. When TypeScript infers a single type
Ifrom(arg: infer I) => voidacross a union of function types, it must find a type that satisfies all parameter positions simultaneously. That’s the intersection. - This is a consequence of how function parameters are contravariant in TypeScript: a function that accepts
A & Bis assignable to both(arg: A) => voidand(arg: B) => void.
Common uses
- Merging plugin registrations where each plugin declares its own slice of a shared context object.
- Combining event handler maps from multiple sources into a single interface.
- Flattening mapped types that produce unions of partial objects.