Intersection
Challenge
Implement the type version of Lodash.intersection with a little difference. Intersection
type Res = Intersection<[[1, 2], [2, 3], [2, 2]]>; // expected to be 2
type Res1 = Intersection<[[1, 2, 3], [2, 3, 4], [2, 2, 3]]>; // expected to be 2 | 3
type Res2 = Intersection<[[1, 2], [3, 4], [5, 6]]>; // expected to be never
type Res3 = Intersection<[[1, 2, 3], [2, 3, 4], 3]>; // expected to be 3
type Res4 = Intersection<[[1, 2, 3], 2 | 3 | 4, 2 | 3]>; // expected to be 2 | 3
type Res5 = Intersection<[[1, 2, 3], 2, 3]>; // expected to be never
Solution
Zur Lösung des Problems können wir einfach eine Schnittmenge aus allen Elementen der Tupeln bilden. Somit erhalten wir alle Elemente, die in allen Elementen enthalten sind, hierzu einige Beispiele:
2 | 3 & 1 | 2 => 2
3 & 1 | 2 | 3 => 3
3 & 1 | 2 => Nichts, da keinen uberschneidungen vorliegen.
Nun extrahieren wir einfach jedes Element der Tupel, und falls die Typvariable H eine Tupel ist, können wir mit dem Lookup typ [number] alle Elemente als Vereinigung erhalten. Sollte H bereits eine number oder Vereinigung sein, so müssen wir nichts machen, und vereinigen immer H mit den restlichen Elementen der Tupel:
type Intersection<T extends unknown[]> = T extends [infer H, ...infer R]
? H extends readonly any[]
? H[number] & Intersection<R>
: H & Intersection<R>
: number;