Pick
Challenge
Implement the built-in Pick<T, K> generic without using it.
Constructs a type by picking the set of properties K from T
For example:
interface Todo {
title: string;
description: string;
completed: boolean;
}
type TodoPreview = MyPick<Todo, "title" | "completed">;
const todo: TodoPreview = {
title: "Clean room",
completed: false,
};
Solution
Zur Lösung dieses Problems werden wir Lookup Types sowie einen Mapped Type nutzen.
Einfach beschrieben dienen Lookup-Typen oder auch Indexed Access Type dazu, einen Typ anhand seines Namens aus einem anderen Typ zu extrahieren. Die Syntax ähnelt dabei einem üblichen Zugriff auf eine Eigenschaft in einem Objekt:
interface Person {
name: string;
age: number;
location: string;
}
type P1 = Person["name"]; // string
Mapped Types ermöglichen die Umwandlung jeder Eigenschaft eines Typs in einen neuen Typ.
type OptionsFlags<Type> = {
[Property in keyof Type]: boolean;
};
Nun liegt die Lösung des Problems darin, über die Schlüssel des übergebenen Typs zu laufen und zu prüfen, ob der aktuelle Schlüsselwert der Iteration eines der Elemente der Vereinigung entspricht. Als Kondition für den Eingabewert definieren wir eine Index-Signatur und das zweite Typargument muss ein Attribut aus dem Objekt-Typ sein
/**
* `U extends keyof T`: Für U dürfen nur Attribute von T genutzt werden
* `[MappedKey in Keys]`: Die übergebene Vereinigung aus U wird mittels 'in' iteriert
*/
type MyPick<T extends { [] }, U extends keyof T> = {
[key in U]: T[key];
};