Detaillierte Erklärung des TS-Objekt-Spread-Operators und des Rest-Operators

Detaillierte Erklärung des TS-Objekt-Spread-Operators und des Rest-Operators

Überblick

TypeScript 2.1 fügt Unterstützung für den Object Spread Operator und den Rest Properties Proposal hinzu, der in ES2018 standardisiert wird. Die Rest- und Spread-Attribute können typsicher verwendet werden.

Objektrestattribut

Angenommen, es wurde ein einfaches Literalobjekt mit drei Eigenschaften definiert

const marius = {
  Name: "Marius Schulz",
  Website: "https://mariusschulz.com/",
  twitterHandle: "@mariusschulz"
};

Mithilfe der Destrukturierungssyntax von ES6 können mehrere lokale Variablen erstellt werden, um die Werte der entsprechenden Eigenschaften zu speichern. TypeScript leitet den Typ jeder Variablen korrekt ab:

const { Name, Website, Twitter-Handle } = Marius;

Name; // Typ Zeichenfolge
website; // Typ Zeichenfolge
twitterHandle; // Typ Zeichenfolge

Das ist zwar alles richtig, aber nichts Neues. Zusätzlich zum Extrahieren einer Reihe von Eigenschaften, die von Interesse sind, können Sie mit der ...-Syntax auch alle verbleibenden Eigenschaften in einem Restelement sammeln:

const { twitterHandle, ...rest } = marius;

twitterHandle; // Typ Zeichenfolge
rest; // Typ { Name: Zeichenfolge; Website: Zeichenfolge; }

TypeScript bestimmt den richtigen Typ für die resultierenden lokalen Variablen. Während die Variable „twitterHandle“ ein einfacher String ist, handelt es sich bei der Restvariable um ein Objekt mit den verbleibenden zwei Eigenschaften, die nicht destrukturiert wurden.

Erweiterte Objekteigenschaften

Angenommen, wir möchten mit der fetch()-API eine HTTP-Anfrage stellen. Es akzeptiert zwei Argumente: eine URL und ein Optionsobjekt, das alle benutzerdefinierten Einstellungen für die Anforderung enthält.

Sie können in Ihrer Anwendung Aufrufe von fetch() kapseln und sowohl Standardoptionen als auch spezifische Einstellungen bereitstellen, die diese für eine bestimmte Anforderung überschreiben. Diese Konfigurationselemente ähneln den folgenden:

const Standardoptionen = {
  Methode: "GET",
  Anmeldeinformationen: „gleiche Herkunft“
};

const Anforderungsoptionen = {
  Methode: "POST",
  Weiterleitung: „folgen“
};

Mithilfe der Objekterweiterung können zwei Objekte zu einem neuen Objekt zusammengeführt und anschließend an die Methode fetch() übergeben werden.

// Typ { Methode: Zeichenfolge; Umleitung: Zeichenfolge; Anmeldeinformationen: Zeichenfolge; }
const Optionen = {
  ...Standardoptionen,
  ...AnfrageOptionen
};

Die Objekterweiterungseigenschaft erstellt ein neues Objekt, kopiert alle Eigenschaftswerte in defaultOptions und kopiert dann alle Eigenschaftswerte in requestOptions der Reihe nach von links nach rechts. Das Endergebnis ist wie folgt:

console.log(Optionen);
// {
// Methode: "POST",
// Anmeldeinformationen: "gleiche Herkunft",
// Weiterleitung: "folgen"
// }

Beachten Sie, dass die Reihenfolge der Zuweisung wichtig ist. Tritt eine Eigenschaft in beiden Objekten auf, so ersetzt die später zugewiesene die früher zugewiesene.

Natürlich versteht TypeScript diese Reihenfolge. Wenn daher mehrere Erweiterungsobjekte eine Eigenschaft mit demselben Schlüssel definieren, ist der Typ dieser Eigenschaft im resultierenden Objekt der Typ der zuletzt zugewiesenen Eigenschaft, da er die zuvor zugewiesene Eigenschaft überschreibt:

const obj1 = { prop: 42 };
const obj2 = { prop: "Hallo Welt" };

const result1 = { ...obj1, ...obj2 }; // Typ { prop: string }
const result2 = { ...obj2, ...obj1 }; // Typ { prop: Zahl }

Erstellen Sie eine oberflächliche Kopie eines Objekts

Mithilfe der Objektverteilung können flache Kopien von Objekten erstellt werden. Nehmen wir an, wir möchten aus einem vorhandenen To-do-Element ein neues To-do-Element erstellen, indem wir ein neues Objekt erstellen und alle Eigenschaften kopieren. Mit Objekten ist das ganz einfach:

const todo = {
  Text: "Blumen gießen",
  abgeschlossen: falsch,
  Schlagworte: ["Garten"]
};

const shallowCopy = { ...todo };

Tatsächlich erhalten Sie ein neues Objekt mit allen kopierten Eigenschaftswerten:

Konsole.log(todo === flachKopie);
// FALSCH

Konsole.log(flache Kopie);
// {
// Text: "Blumen gießen",
// abgeschlossen: false,
// Tags: ["Garten"]
// }

Jetzt können Sie die Texteigenschaft ändern, ohne das ursprüngliche Aufgabenelement zu ändern:

hallowCopy.text = "Rasen mähen";

Konsole.log(flache Kopie);
// {
// Text: "Rasen mähen",
// abgeschlossen: false,
// Tags: ["Garten"]
// }

Konsole.log(todo);
// {
// Text: "Blumen gießen",
// abgeschlossen: false,
// Tags: ["Garten"]
// }

Das neue To-Do-Element verweist jedoch auf dasselbe Tag-Array wie das erste. Da es sich um eine oberflächliche Kopie handelt, wirkt sich die Änderung des Arrays auf beide Todos aus.

flachCopy.tags.push("Wochenende");

Konsole.log(flache Kopie);
// {
// Text: "Rasen mähen",
// abgeschlossen: false,
// tags: ["Garten", "Wochenende"]
// }

Konsole.log(todo);
// {
// Text: "Blumen gießen",
// abgeschlossen: false,
// tags: ["Garten", "Wochenende"]
// }

Wenn Sie eine vollständige Kopie eines serialisierten Objekts erstellen möchten, sollten Sie jsON.parse(jsON.stringify(obj)) oder andere Methoden wie object.assign() verwenden. Objekterweiterungen kopieren nur Eigenschaftswerte, was zu unerwartetem Verhalten führen kann, wenn ein Wert ein Verweis auf ein anderes Objekt ist.

Keyof- und Lookup-Typen

JS ist eine sehr dynamische Sprache. Das Erfassen der Semantik bestimmter Operationen in einem statischen Typsystem kann manchmal schwierig sein. Nehmen wir als Beispiel eine einfache Prop-Funktion:

Funktion prop(obj, Schlüssel) {
  returniere Objekt[Schlüssel];
}

Es nimmt ein Objekt und einen Schlüssel und gibt den Wert der entsprechenden Eigenschaft zurück. Verschiedene Eigenschaften eines Objekts können völlig unterschiedliche Typen haben, und wir wissen nicht einmal, wie „obj“ aussieht.

Wie schreiben Sie diese Funktion also in TypeScript? Versuchen Sie zunächst Folgendes:

Bei diesen beiden Typanmerkungen muss „obj“ ein Objekt und „key“ eine Zeichenfolge sein. Wir haben nun die Menge der möglichen Werte für beide Parameter eingeschränkt. TS folgert jedoch immer noch als beliebigen Rückgabetyp:

const todo = {
  ID: 1,
  Text: "Milch kaufen",
  fällig: neues Datum (31.11.2016)
};

const id = prop(todo, "id"); // beliebig
const text = prop(todo, "text"); // beliebig
const due = prop(todo, "due"); // beliebig

Ohne weitere Informationen weiß TypeScript nicht, welcher Wert für den Schlüsselparameter übergeben wird, und kann daher keinen spezifischeren Rückgabetyp für die Prop-Funktion ableiten. Um dies zu erreichen, müssen wir mehr Typinformationen bereitstellen.

Keyof-Operator

APIs, die Eigenschaftsnamen als Parameter verwenden, sind in JS recht verbreitet, aber bisher gab es keine Möglichkeit, die in diesen APIs auftretenden Typbeziehungen auszudrücken.

TypeScript 2.1 fügt den Keyof-Operator hinzu. Geben Sie den Indextyp query oder keyof ein. Der vom Indextyp query keyof T erzeugte Typ ist der Attributname von T. Angenommen, wir haben die folgende Todo-Schnittstelle definiert:

Schnittstelle Todo {
  ID: Nummer;
  Text: Zeichenfolge;
  Fälligkeitsdatum;
}

Sie können den Keyof-Operator auf den Todo-Typ anwenden, um den Typ aller seiner Eigenschaftsschlüssel zu erhalten, der eine Vereinigung der Zeichenfolgenliteraltypen darstellt.

Typ TodoKeys = Schlüssel von Todo; // "id" | "text" | "fällig"

Natürlich können Sie den Union-Typ „id“ | „text“ | „due“ auch manuell schreiben, anstatt keyof zu verwenden, aber das ist umständlich, fehleranfällig und schwierig zu warten. Außerdem sollte es sich eher um eine Todo-spezifische Lösung als um eine allgemeine handeln.

Indextypabfrage

Mit keyof können wir jetzt die Typannotation der Prop-Funktion verbessern. Wir möchten keine beliebigen Zeichenfolgen mehr als Schlüsselparameter akzeptieren. Stattdessen verlangen wir, dass der Parameterschlüssel tatsächlich für den Typ des übergebenen Objekts vorhanden ist.

Funktion prop<T, K erweitert Schlüssel von T>(Objekt: T, Schlüssel: K) {
  returniere Objekt [Schlüssel]
}

TypeScript folgert nun, dass der Rückgabetyp der Prop-Funktion T[K] ist. Dies wird als indizierte Typsuche oder Typsuche bezeichnet. Es stellt den Typ des Attributs K vom Typ T dar. Wenn wir nun unten über die Methode prop auf die drei Eigenschaften von todo zugreifen, hat jede Eigenschaft den richtigen Typ:

const todo = {
  ID: 1,
  Text: "Milch kaufen",
  fällig: neues Datum (31.11.2016)
};

const id = prop(todo, "id"); // Nummer
const text = prop(todo, "text"); // Zeichenfolge
const due = prop(todo, "fällig"); // Datum

Was passiert nun, wenn Sie einen Schlüssel übergeben, der im To-Do-Objekt nicht vorhanden ist?

Der Compiler wird sich beschweren, was gut ist, denn es verhindert, dass wir versuchen, eine Eigenschaft zu lesen, die nicht existiert.

Ein weiteres Beispiel aus der Praxis finden Sie in der Methode Object.entries() in der Typdeklarationsdatei lib.es2017.object.d.ts, die mit dem TypeScript-Compiler bereitgestellt wird:

Schnittstelle ObjectConstructor {
  // ...
  Einträge<T erweitert { [Schlüssel: Zeichenfolge]: beliebig }, K erweitert Schlüssel von T>(o: T): [Schlüssel von T, T[K]][];
  // ...
}

Die Methode „entrys“ gibt ein Array von Tupeln zurück, wobei jedes Tupel einen Attributschlüssel und den entsprechenden Wert enthält. Zugegeben, im Rückgabetyp gibt es viele eckige Klammern, aber wir achten immer auf Typsicherheit.

Oben finden Sie eine ausführliche Erläuterung des TS-Objekt-Spread-Operators und des Rest-Operators. Weitere Informationen zum TS-Objekt-Spread-Operator und dem Rest-Operator finden Sie in den anderen verwandten Artikeln auf 123WORDPRESS.COM!

Das könnte Sie auch interessieren:
  • Zusammenfassung der Anwendungsbeispiele für den JavaScript-Spread-Operator [basierend auf ES6]
  • Verständnis und Anwendungsszenarien von ES6-Erweiterungsoperatoren
  • Beispiele für die Verwendung des ES6-Spread-Operators
  • Detaillierte Erläuterung der Verwendung und Vorsichtsmaßnahmen des ES6-Erweiterungsoperators
  • Analyse von Verwendungsbeispielen für ES6-Erweiterungsoperatoren und Restoperatoren
  • Beispielanalyse der ES6-Array-Erweiterungsoperatoroperation
  • Neue Funktionen von JS ES: Einführung in Erweiterungsoperatoren

<<:  So konfigurieren Sie NAS unter Windows Server 2019

>>:  MySQL Master-Slave-Prinzip und Konfigurationsdetails

Artikel empfehlen

Mehrere Möglichkeiten zum Verbinden von Tabellen in MySQL

Die Verbindungsmethode in der MySQL-Tabelle ist e...

Warum sollte CSS im Head-Tag platziert werden?

Denken Sie darüber nach: Warum sollte css im head...

MySQL-Tabellenfeld Zeiteinstellung Standardwert

Anwendungsszenario In der Datentabelle muss die A...

So erzielen Sie mit CSS einen Daten-Hotspot-Effekt

Die Wirkung ist wie folgt: analysieren 1. Hier se...

MySQL View-Prinzipanalyse

Inhaltsverzeichnis Aktualisierbare Ansichten Leis...

Detaillierte Installation und Verwendung der Virtuoso-Datenbank unter Linux

Ich habe kürzlich einige Dinge zu verknüpften Dat...

Analyse und Lösungen für Probleme bei der Verwendung von Label-Tags

Ich habe kürzlich bei einer bestimmten Aufgabe das...

Lösen Sie das Problem, dass Docker das MySQL-Image zu langsam zieht

Nachdem wir eine halbe Stunde lang versucht hatte...

Implementierung der Anmeldeseite des tatsächlichen Kampfprotokolls von Vue

Inhaltsverzeichnis 1. Vorbereitende Maßnahmen 1.1...

React+axios implementiert die Suchbenutzerfunktion von GitHub (Beispielcode)

laden Anforderung erfolgreich Anforderung fehlges...

Eine kurze Analyse der MySQL-Kardinalitätsstatistiken

1. Was ist die Kardinalität? Mit Kardinalität wir...

Vue verwendet WebSocket, um die Chat-Funktion zu simulieren

Der Effekt zeigt, dass sich zwei Browser gegensei...