While skimming through the TypeScript challenges, I came across a particularly interesting one: How to turn a union to an intersection.
Unable to figure it out myself, I turned to the solutions where I found a great approach here and an even greater explanation given here by @jcalz.
The only problem in my way was this question: effectively a user tried to break down the solution in multiple separate statements and, to my surprise, the result was not the same. Instead of foo & bar
we were getting foo | bar
. Putting the solution back together as a "one-liner" the result gets "restored": foo & bar
.
// Type definition
type UnionToIntersection<U> = (U extends any ? (arg: U) => any : never) extends ((arg: infer I) => void)
? I
: never;
// As expected ('foo' & 'bar' is never)
type I = UnionToIntersection<'foo' | 'bar'>; // never
// Let's break-down `UnionToIntersection`
type A = 'foo' | 'bar';
type B = A extends any ? (arg: A) => any : never // (arg: A) => any;
// This should have been 'foo' & 'bar' (never) just like `type I`
type C = B extends ((arg: infer I) => void) ? I : never // 'foo' | 'bar'
What's going on here? Shouldn't type I
and type C
be the same?