Append to object
Challenge
Implement a type that adds a new field to the interface. The type takes the three arguments. The output should be an object with the new field.
For example
type Test = { id: "1" };
type Result = AppendToObject<Test, "value", 4>; // expected to be { id: '1', value: 4 }
Solution
Zur Lösung dieses Problems können wir eine sogenannte Intersection (Schnittmenge) zwischen zwei Objekt-Typen nutzen, um ein neues Objekt zu erzeugen. Generell kommen Intersections bei der Erweiterung/ Veränderung von Objekten oft zum Einsatz.
type AppendToObject<T, U, V> = T & { [P in U]: V };
Das Problem ist allerdings, dass dies nicht richtig funktioniert, da falls U bereits in T vorhanden ist, eine Intersection nicht möglich ist:
{id: "1"} & {id:"4"} // never
{id: "1"} & { value: 4} // {id: '1', value: 4}
Wir benötigen also eine andere Lösung. Eine Möglichkeit z.B. ist es nun, einen Mapped Type zu erstellen, bei dem über eine Vereinigung der Eigenschaft aus T und U iteriert wird.
Dies funktioniert, man muss allerdings für jedes Attribut prüfen, ob auch das Attribut in T existiert, da sonst kein Zugriff auf den Wert der Eigenschaft möglich ist.
type AppendToObject<T, U extends string, V> = {
[Key in keyof T | U]: Key extends keyof T ? T[Key] : V;
};