ObjectFromEntries

Challenge

Implement the type version of Object.fromEntries

For example:

interface Model {
  name: string;
  age: number;
  locations: string[] | null;
}

type ModelEntries =
  | ["name", string]
  | ["age", number]
  | ["locations", string[] | null];

type result = ObjectFromEntries<ModelEntries>; // expected to be Model

Solution

Zur Lösung dieses Problems können wir wieder einen mapped type erstellen. Wichtig ist es hier, den generischen Typen auf eine Tupel mit zwei Werten zu beschränken:

type ObjectFromEntries<T extends [key: string, value: unknown]> = ...

Nun können wir mit Key in T[0] über alle ersten Elemente aus der Tupel laufen. Nun einfach den Wert T[1] zu verwenden funktioniert nicht, da wir somit alle Typen an der Stelle (z.B. string | number | string[] | null) erhalten. Stattdessen können wir das aktuelle Element aus der Vereinigung mittels Extract herausziehen, und dann den Wert mittels eines Index Type oder Lookup Type erhalten:

type ObjectFromEntries<T extends [key: string, value: unknown]> = {
  [key in T[0]]: Extract<T, [key, unknown]>[1];
};

References