ÜberblickTypeScript 2.1 führte zugeordnete Typen ein, eine leistungsstarke Ergänzung des Typsystems. Im Wesentlichen ermöglichen uns zugeordnete Typen, durch die Zuordnung von Attributtypen neue Typen aus vorhandenen Typen zu erstellen. Konvertiert jede Eigenschaft eines vorhandenen Typs gemäß den von uns angegebenen Regeln. Die konvertierten Attribute bilden den neuen Typ. Mithilfe zugeordneter Typen können Sie die Auswirkungen von Methoden wie Object.freeze() im Typsystem erfassen. Sobald ein Objekt eingefroren ist, können Sie keine Eigenschaften mehr hinzufügen, ändern oder löschen. Sehen wir uns an, wie dies im Typsystem codiert werden kann, ohne zugeordnete Typen zu verwenden: Schnittstelle Punkt { x: Zahl; y: Zahl; } Schnittstelle FrozenPoint { schreibgeschützt x: Zahl; schreibgeschützt y: Zahl; } Funktion freezePoint(p: Punkt): FrozenPoint { gibt Objekt.freeze(p) zurück; } const Herkunft = freezePoint({ x: 0, y: 0 }); // Fehler! Kann 'x' nicht zuweisen, da es // ist eine Konstante oder eine schreibgeschützte Eigenschaft. Ursprung.x = 42; Wir definieren eine Point-Schnittstelle, die zwei Eigenschaften enthält, x und y. Wir definieren außerdem eine weitere Schnittstelle, FrozenPoint, die mit Point identisch ist, außer dass alle ihre Eigenschaften mit readonly als schreibgeschützte Eigenschaften definiert sind. Die Funktion „freezePoint“ akzeptiert einen Punkt als Argument, friert ihn ein und gibt dann dasselbe Objekt an den Anrufer zurück. Der Typ des Objekts wurde jedoch in FrozenPoint geändert, sodass seine Eigenschaften statisch als schreibgeschützt typisiert sind. Aus diesem Grund tritt bei dem Versuch, der Eigenschaft x den Wert 42 zuzuweisen, ein Fehler in TypeScript auf. Zur Laufzeit wird die Zuweisung entweder einen TypeError auslösen (strikter Modus) oder stillschweigend fehlschlagen (nicht strenger Modus). Das obige Beispiel lässt sich zwar kompilieren und funktioniert korrekt, weist jedoch zwei wesentliche Nachteile auf:
Verwenden zugeordneter Typen zum Erstellen von Object.freeze()Sehen wir uns an, wie Object.freeze() in der Datei lib.d.ts definiert ist: /** * Verhindert die Änderung vorhandener Eigenschaftsattribute und -werte und das Hinzufügen neuer Eigenschaften. * @param o Objekt, dessen Attribute gesperrt werden sollen. */ freeze<T>(o: T): Nur Lesen<T>; Der Rückgabetyp dieser Methode ist Readonly<T>, ein Zuordnungstyp, der wie folgt definiert ist: Typ schreibgeschützt<T> = { schreibgeschützt [P in Schlüssel von T]: T[P] }; Diese Syntax kann zunächst entmutigend wirken, also lassen Sie uns sie Schritt für Schritt aufschlüsseln:
Da der Typ Readonly<T> generisch ist, wird jeder Typ, den wir für T bereitstellen, korrekt in Object.freeze() gepackt. const Herkunft = Objekt.freeze({ x: 0, y: 0 }); // Fehler! Kann 'x' nicht zuweisen, da es // ist eine Konstante oder eine schreibgeschützte Eigenschaft. Ursprung.x = 42; Die Syntax des Mapping-Typs ist intuitiverDieses Mal verwenden wir den Punkttyp als Beispiel, um grob zu erklären, wie die Typzuordnung funktioniert. Bitte beachten Sie, dass das Folgende nur zu Erklärungszwecken dient und den von TypeScript verwendeten Analysealgorithmus nicht genau wiedergibt. Beginnen Sie mit dem Typalias: Typ ReadonlyPoint = Readonly<Punkt>; Jetzt können wir den Typ Point durch den generischen Typ T in Readonly<T> ersetzen: Typ ReadonyPoint = { schreibgeschützt [P in keyof Point]: Punkt[P] }; Da wir nun wissen, dass T Point ist, können wir die Vereinigung der durch keyof Point dargestellten Zeichenfolgenliteraltypen bestimmen: Typ ReadonlyPoint = { schreibgeschützt [P in "x" | "y"]: Punkt[p] }; Typ P stellt jede Eigenschaft x und y dar. Schreiben wir sie als separate Eigenschaften und entfernen die zugeordnete Typsyntax. Typ ReadonlyPoint = { schreibgeschütztes x: Punkt["x"]; schreibgeschütztes y: Punkt["y"]; }; Schließlich können wir die beiden Nachschlagetypen analysieren und durch die konkreten Typen x und y ersetzen, die beide Zahlen sind. Typ ReadonlyPoint = { schreibgeschützt x: Zahl; schreibgeschützt y: Zahl; }; Schließlich ist der resultierende ReadonlyPoint-Typ derselbe wie der FrozenPoint-Typ, den wir manuell erstellt haben. Weitere Beispiele für ZuordnungstypenDen integrierten Typ Readonly<T> haben wir bereits oben in der Datei lib.d.ts gesehen. Darüber hinaus definiert TypeScript andere zugeordnete Typen, die in verschiedenen Situationen nützlich sind. wie folgt: /** * Alle Eigenschaften in T optional machen */ Typ Partial<T> = { [P in Tonart T]?: T[P] }; /** * Wählen Sie aus T eine Reihe von Eigenschaften K */ Typ Pick<T, K erweitert Schlüssel von T> = { [P in K]: T[P] }; /** * Konstruieren Sie einen Typ mit einer Reihe von Eigenschaften K vom Typ T */ Typ Record<K erweitert Zeichenfolge, T> = { [P in K]: T }; Hier sind zwei weitere Beispiele für Zuordnungstypen. Sie können bei Bedarf auch eigene schreiben: /** * Alle Eigenschaften in T nullwertfähig machen */ Typ Nullable<T> = { [P in Tonart T]: T[P] | null }; /** * Wandeln Sie alle Eigenschaften von T in Zeichenfolgen um */ Typ Stringify<T> = { [P in Tonart T]: Zeichenfolge }; Interessant sind auch Kombinationen aus zugeordneten Typen und Vereinigungen: Typ X = Nur-Lese<Nullable<Stringify<Punkt>>>; // Typ X = { // schreibgeschützt x: Zeichenfolge | null; // schreibgeschützt y: string | null; // }; Reale Anwendungsfälle für Mapping-TypenMapping-Typen werden in der Praxis häufig verwendet. Schauen wir uns React und Lodash an:
Bessere Typinferenz für LiteraleZeichenfolgen-, numerische und boolesche Literaltypen (z. B. „abc“, 1 und true) wurden bisher nur abgeleitet, wenn eine explizite Typanmerkung vorhanden war. Ab TypeScript 2.1 wird bei Literaltypen immer davon ausgegangen, dass sie Standardwerte haben. In TypeScript 2.0 wurde das Typsystem um mehrere neue Literaltypen erweitert:
Der Typ einer Konstantenvariable oder einer schreibgeschützten Eigenschaft ohne Typanmerkung wird als der Typ des Literalinitialisierers abgeleitet. Der Typ einer initialisierten Let-Variable, Var-Variable, eines Parameters oder einer nicht schreibgeschützten Eigenschaft ohne Typanmerkung wird als der erweiterte Literaltyp des Anfangswerts abgeleitet. Der erweiterte Typ eines Zeichenfolgenliterals ist Zeichenfolge, der erweiterte Typ eines Zahlenliterals ist Zahl, der erweiterte Typ eines True- oder False-Literals ist Boolean und der erweiterte Typ eines Aufzählungsliterals ist Aufzählung. Bessere Inferenz von KonstantenvariablenBeginnen wir mit lokalen Variablen und dem Schlüsselwort var. Wenn TypeScript die folgende Variablendeklaration sieht, folgert es, dass die Variable baseUrl vom Typ String ist: var baseUrl = "https://example.com/"; // Abgeleiteter Typ: Zeichenfolge Dasselbe gilt für Variablen, die mit dem Schlüsselwort let deklariert werden. let baseUrl = "https://example.com/"; // Abgeleiteter Typ: Zeichenfolge Es wird davon ausgegangen, dass beide Variablen vom Typ „String“ sind, da sie sich jederzeit ändern können. Sie werden mit einem wörtlichen Zeichenfolgenwert initialisiert, können aber später geändert werden. Wenn Sie jedoch eine Variable mit dem Schlüsselwort const deklarieren und sie mit einem Zeichenfolgenliteral initialisieren, ist der abgeleitete Typ nicht mehr Zeichenfolge, sondern der Literaltyp: const baseUrl = "https://example.com/"; // Abgeleiteter Typ: „https://example.com/“ Da sich der Wert einer konstanten Zeichenfolgenvariable nie ändert, ist der abgeleitete Typ spezifischer. Die Variable baseUrl kann keinen anderen Wert als „https://example.com/“ enthalten. Die wörtliche Typinferenz funktioniert auch für andere primitive Typen. Wenn Sie eine Konstante mit einem direkten numerischen oder booleschen Wert initialisieren, wird der Literaltyp abgeleitet: const HTTPS_PORT = 443; // Abgeleiteter Typ: 443 const erinnere mich = true; // Abgeleiteter Typ: true Wenn der Initialisierer ein Enumerationswert ist, wird entsprechend der Literaltyp abgeleitet: Aufzählung FlexDirection { Reihe, Spalte } Konstante Richtung = FlexDirection.Spalte; // Abgeleiteter Typ: FlexDirection.Column Beachten Sie, dass der Richtungstyp FlexDirection.Column ist, ein Enumerationsliteraltyp. Wenn Sie das Schlüsselwort let oder var verwenden, um eine Richtungsvariable zu deklarieren, sollte ihr abgeleiteter Typ FlexDirection sein. Bessere schreibgeschützte EigenschaftsinferenzÄhnlich wie bei lokalen Konstantenvariablen wird auch bei schreibgeschützten Eigenschaften mit wörtlichen Initialisierern davon ausgegangen, dass sie einen wörtlichen Typ haben: Klasse ApiClient { private schreibgeschützte Basis-URL = "https://api.example.com/"; // Abgeleiteter Typ: „https://api.example.com/“ get(Endpunkt: Zeichenfolge) { // ... } } Schreibgeschützte Klasseneigenschaften können nur direkt oder im Konstruktor initialisiert werden. Der Versuch, den Wert an anderer Stelle zu ändern, führt zu einem Kompilierungsfehler. Daher ist es sinnvoll, den Literaltyp einer schreibgeschützten Klasseneigenschaft abzuleiten, da sich ihr Wert nicht ändert. Natürlich hat TypeScript keine Ahnung, was zur Laufzeit passiert: Eine mit „readonly“ gekennzeichnete Eigenschaft kann jederzeit durch JavaScript-Code geändert werden. Der Readonly-Modifikator schränkt lediglich den Zugriff auf die Eigenschaft aus TypeScript-Code ein und tut zur Laufzeit nichts. Das heißt, es wird während der Kompilierung gelöscht und erscheint nicht im generierten JS-Code. Nützlichkeit abgeleiteter LiteraltypenSie fragen sich vielleicht, warum es sinnvoll ist, Literaltypen für Konstantenvariablen und schreibgeschützte Eigenschaften abzuleiten. Betrachten Sie den folgenden Code: const HTTP_GET = "GET"; // Abgeleiteter Typ: "GET" const HTTP_POST = "POST"; // Abgeleiteter Typ: "POST" Funktion get(URL: Zeichenfolge, Methode: "GET" | "POST") { // ... } get("https://example.com/", HTTP_GET); Wenn der abgeleitete Typ der HTTP_GET-Konstante ein String statt „GET“ wäre, würden Sie einen Kompilierungsfehler erhalten, weil Sie HTTP_GET nicht als zweites Argument an die Get-Funktion übergeben können:
Natürlich ist die Übergabe beliebiger Zeichenfolgen als Funktionsargumente nicht zulässig, wenn das entsprechende Argument nur zwei bestimmte Zeichenfolgenwerte zulässt. Wenn jedoch für die beiden Konstanten die Literaltypen „GET“ und „POST“ abgeleitet werden, klappt alles. Oben finden Sie eine ausführliche Erläuterung der TypeScript-Mapping-Typen und der besseren wörtlichen Typinferenz. Weitere Informationen zu TS finden Sie in den anderen verwandten Artikeln auf 123WORDPRESS.COM! Das könnte Sie auch interessieren:
|
>>: So implementieren Sie geplante MySQL-Aufgaben unter Linux
Lösung: Setzen Sie den Zielattributwert des Links ...
Problembeschreibung Installieren Sie nginx auf Te...
In diesem Artikel wird der Unterschied zwischen P...
Drei Funktionen: 1. Automatische vertikale Zentrie...
1. Technische Punkte Vite-Version vue3 ts Integri...
Heute habe ich die MySQL-Datenbank erneut auf mei...
Vorwort Ich habe viele Blogs gelesen und von viel...
Go ist eine Open-Source-Programmiersprache, die d...
Zuvor habe ich mehrere Möglichkeiten vorgestellt,...
Hinweis: nginx über brew installiert Stammverzeic...
Inhaltsverzeichnis 1. Ressourcen und Konstruktion...
Das Betriebssystem für die folgenden Inhalte ist:...
Um VMWare unter Linux zu installieren, müssen Sie...
Vorwort Wer schon einmal mit MySQL gespielt hat, ...
Chinesische Dokumentation: https://router.vuejs.o...