Includes

Challenge

Implement the JavaScript Array.includes function in the type system. A type takes the two arguments. The output should be a boolean true or false.

For example:

type isPillarMen = Includes<["Kars", "Esidisi", "Wamuu", "Santana"], "Dio">; // expected to be `false`

Solution

Eine einfachere Lösung ist es, auch hier einen Lookup-Typ zu nutzen. Hier ist das bereits vordefinierte readonly [] auf dem Eingabetyp angegeben. Nutzt man den Lookup-Typ number, dann erhält man eine Vereinigung der Elemente aus dem Array (nur bei readonly Arrays, und damit Tupeln möglich).

(["Kars", "Esidisi", "Wamuu", "Santana"] as readonly [])[number]; // Kars | Esidisi | Wamuu ....

Nun ist es möglich, jeden Wert des Arrays mit dem übergebenen Typ zu vergleichen, da Vereinigungen in konditionellen Typen distributiv sind.

// Beispiel: T = ["Kars", "Esidisi"] U = "Dio"
// "Kars" extends "Dio" ? true : false
// "Esidisi" extends "Dio" ? true : false
type Includes<T extends readonly [], U> = T[number] extends U ? true : false;

Alternativ kann man auch wieder einen konditionellen Typen infer nutzen, um nacheinander ein Element nach dem anderen aus dem Array zu extrahieren und auf die Gleichheit mit U zu prüfen:

type Includes<T extends readonly any[], U> = T extends [
  infer First,
  ...infer Last
]
  ? Equal<First, U> extends true
    ? true
    : Includes<Last, U>
  : false;

References

Generics Constraints Conditonal Types Lookup Types