UnionToIntersection Utility Type
Going from a union (`A | B | C`) to an intersection (`A & B & C`) is what you need when you want to merge handler shapes, deduce the most-specific type, or express a 'must satisfy all branches' constraint. TypeScript has no built-in for this, but a single conditional with `infer` does the job. This snippet builds the type, walks through how distributive conditionals make it work, and ties it to a concrete LastInUnion / merged-handlers example.
194 views
5
type UnionToIntersection<U> = (U extends unknown ? (k: U) => void : never) extends (k: infer I) => void ? I : never;
type Mixed = UnionToIntersection<{ a: string } | { b: number }>;
const merged = { 'a': 'x', 'b': 1 } as Mixed;
console.log(`${merged.a} ${merged.b}`);The trick is twofold. First, U extends unknown ? (k: U) => void : never is a distributive conditional that turns A | B into ((k: A) => void) | ((k: B) => void). Second, the outer extends (k: infer I) => void infers I from a union of function parameters, which TypeScript resolves in contravariant position by intersecting them, giving A & B. Distributive conditionals only fire when the checked type is a bare type parameter, which is why the extends unknown guard is structured that way. Use this anywhere you need to merge handler maps, derive a LastInUnion helper, or feed a keyof union into an indexed access.
2 more snippets in this entry are available for premium members.
Upgrade to Premium