Filter

Challenge

Implement the type Filter<T, Predicate> takes an Array T, primitive type or union primitive type Predicate and returns an Array include the elements of Predicate.

Solution

Zur Lösung des Problems können wir wieder mittels infer das jeweils erste Element der Tupel extrahieren. Bevor wir dies tun, sollten wir jedoch noch ein weiteres Typargument in Form eines Akkumulators anlegen, um die gefilterten Elemente zwischenzuspeichern.

type Filter<T extends unknown[], U, Acc extends any[] = []> = T extends [
  infer H,
  ...infer R
]
  ? ....

Anschließend prüfen wir nun für die Typvariable H, ob diese der übergebenen Vereinigung entspricht. Da Vereinigungen in konditionellen Typen distributiv sind, wird H gegen jedes Element der Vereinigung geprüft. Ist H in der Vereinigung enthalten, so fügen wir es einfach dem Akkumulator hinzu.

type Filter<T extends unknown[], U, Acc extends any[] = []> = T extends [
  infer H,
  ...infer R
]
  ? H extends U
    ? Filter<R, U, [...Acc, H]>
    : Filter<R, U, Acc>
  : Acc;

References