Die Index Signature ist ein Mechanismus zur Beschreibung von Objekttypen, deren Schlüssel im Voraus unbekannt sind (oder dynamisch hinzugefügt werden können), während die Werte einem bestimmten Typ entsprechen. Sie ermöglicht das Erstellen von Wörterbuchobjekten (map/dictionary), bei denen die Liste der Eigenschaften zur Compilierungszeit unbekannt ist.
Hintergrund: In JavaScript fungieren Objekte häufig als assoziative Arrays. Die statische Typisierung von TypeScript erfordert die Angabe von Typen für Schlüssel und Werte. Die Index Signature löst das Hauptproblem: ein Objekt zu beschreiben, bei dem der Schlüssel keine festgelegte Eigenschaft ist, sondern ein String (oder eine Zahl), während die Werte einen bestimmten Typ haben.
Problem: Bei der Arbeit mit solchen Objekten kann es passieren, dass bekannte Eigenschaften des Objekts mit der Index Signature in Konflikt geraten oder Informationen über spezifische Eigenschaften verloren gehen. Es gibt Nuancen mit vererbten Typen und der Erweiterung der Wörterbuchstruktur.
Lösung: Die Index Signature wird verwendet, um dynamische Eigenschaften zu beschreiben, normalerweise mit einem Schlüssel vom Typ String oder Number, zum Beispiel für Sammlungen, Cache-Objekte oder API-Antworten wie { [key: string]: T }. Um die Kontrolle über den Typ zu behalten, müssen sowohl feste Eigenschaften als auch die Index Signature zusammen beschrieben werden oder, falls erforderlich, Union-Typen gebildet werden.
Beispielcode:
interface StringNumberMap { [key: string]: number; } const map: StringNumberMap = { apples: 2, oranges: 5, bananas: 3 };
Wichtige Merkmale:
Was passiert, wenn man eine feste Eigenschaft mit einem inkompatiblen Typ in ein Interface mit Index Signature hinzufügt?
TypeScript gibt einen Fehler aus, wenn der Typ der Eigenschaft nicht mit dem in der Index Signature angegebenen Typ kompatibel ist.
interface BadDict { [key: string]: number; error: string; // Fehler: string ist nicht kompatibel mit number }
Kann man mehrere Index Signatures mit unterschiedlichen Schlüsseltypen (number und string) gleichzeitig deklarieren?
Ja, das ist möglich, es gibt jedoch eine Nuance: In TypeScript werden Schlüssel vom Typ number automatisch in einen String umgewandelt. Eine Index Signature mit number ist also nur ein Synonym für string-Schlüssel.
interface NumStrDict { [key: string]: number; [key: number]: number; }
Kann man Union-Typen oder Interfaces für Werte in der Index Signature verwenden?
Ja, der Wert kann ein Union-Typ oder ein Interface sein. So können Wörterbücher komplexer Objekte beschrieben werden.
interface Dict { [key: string]: string | number; }
Im Interface der API-Antwort wurde [key: string]: any verwendet. Später enthielt das zurückgegebene Objekt Daten unterschiedlicher Strukturen, was zu Laufzeitfehlern führte und die Wartung des Codes erschwerte.
Vorteile:
Nachteile:
Das Interface für das Cache-Objekt wurde beschrieben, bei dem die Werte einen strengen Typ (zum Beispiel UserData) haben, mit einem Kommentar, dass der Schlüssel userId (string) ist:
interface UserCache { [userId: string]: UserData; }
Vorteile:
Nachteile: