Geschichte der Frage:
Spread (...) und Rest (...) sind eine der beliebtesten modernen Syntaxkonstruktionen, die aus ES6 stammen. In TypeScript haben sie strenge Typisierung erhalten, sodass die Verwendung von Spread und Rest nicht nur bequem, sondern auch sicher ist, wenn man die typischen Einschränkungen einhält.
Problem:
Spread- und Rest-Operationen können eine Fehlerquelle sein, wenn der Typ der Werte nicht berücksichtigt wird oder inkompatible Typen gemischt werden (zum Beispiel, wenn Objekte mit inkompatiblen Eigenschaften oder Arrays unterschiedlicher Typen zusammengeführt werden).
Lösung:
In TypeScript wird Spread verwendet, um Eigenschaften von Objekten und Elemente von Arrays zu kopieren oder zusammenzuführen. Rest ermöglicht es, "restliche" Elemente in einer Funktion oder einem Array zu sammeln, wobei die strenge Typisierung inkompatible Fälle überprüft und Fehler zur Compile-Zeit verhindert.
Codebeispiel:
// Spread mit Objekten const base = { a: 1, b: 2 }; const extended = { ...base, c: 3 }; // extended: { a: number; b: number; c: number } // Rest in Funktionsparametern function sum(...args: number[]): number { return args.reduce((acc, val) => acc + val, 0); } // Spread in Arrays const arr = [1, 2, 3]; const newArr = [...arr, 4, 5];
Wesentliche Merkmale:
Was ist der Unterschied zwischen dem Kopieren eines Objekts über Spread und der Zuweisung durch Referenz?
Spread erstellt ein neues Objekt mit einer Kopie aller aufgelisteten Eigenschaften, aber wenn im Objekt verschachtelte Objekte vorhanden sind, werden diese per Referenz kopiert (shallow copy).
const base = { a: 1, nested: { x: 2 } }; const copy = { ...base }; copy.nested.x = 42; console.log(base.nested.x); // 42
Kann man mit Spread nur bestimmte Eigenschaften kopieren?
Nein, Spread kopiert alle aufgelisteten Eigenschaften des Objekts. Für die Auswahl einzelner verwendet man Destrukturierung:
const { a, ...rest } = { a: 1, b: 2, c: 3 }; // rest: { b: 2, c: 3 }
Was passiert, wenn man zwei Objekte mit den gleichen Eigenschaften über Spread zusammenführt? Wie wirkt sich das auf die Typisierung aus?
Eigenschaften des letzten Objekts überschreiben die Eigenschaften früherer Objekte. Der Typ der letzten Eigenschaft wird dabei als final betrachtet:
const a = { val: 1 }; const b = { val: 'hello' }; const merged = { ...a, ...b }; // merged: { val: string } (statt number)
In einem Projekt entschloss man sich, Konfigurationsparameter über Spread zusammenzuführen. Eines der Objekte hatte die Eigenschaft timeout: number, das andere timeout: string. Es wurden keine Fehler bemerkt, bis zur Laufzeit, als die Funktion aufgrund eines falschen Typs fehlschlug.
Vorteile:
Nachteile:
Es wurde typisierter Spread verwendet, um strenge Schnittstellen zusammenzuführen, sowie Destrukturierung, um unerwünschte Felder zu trennen. Der Compiler erkannte die Fehler sofort.
Vorteile:
Nachteile: