Ausführliche Lektüre und Übungsaufzeichnungen zu bedingten Typen in TypeScript

Ausführliche Lektüre und Übungsaufzeichnungen zu bedingten Typen in TypeScript

In den meisten Programmen müssen wir Entscheidungen auf der Grundlage von Eingaben treffen. TypeScript ist keine Ausnahme. Mithilfe bedingter Typen können Sie die Beziehung zwischen Eingabetypen und Ausgabetypen beschreiben.

Wird für bedingte Urteile verwendet

Wenn „extended“ zum Ausdruck bedingter Urteile verwendet wird, können die folgenden Regeln zusammengefasst werden:

Wenn die Typen auf beiden Seiten von extends gleich sind, kann extends semantisch als === verstanden werden, wie im folgenden Beispiel gezeigt:

Typ Ergebnis1 = „a“ erweitert „abc“? Wahr: Falsch // Falsch
Typ result2 = 123 erweitert 1 ? true : false // false

Wenn der Typ auf der rechten Seite von extends den Typ auf der linken Seite von extends enthält (das heißt, der schmale Typ erweitert den breiten Typ), ist das Ergebnis true, andernfalls false. Sie können sich am folgenden Beispiel orientieren:

Typ Ergebnis3 = Zeichenfolge erweitert Zeichenfolge | Zahl? true : false // true

Wenn „Extendeds“ auf ein Objekt angewendet wird, gilt: Je mehr Schlüssel im Objekt angegeben sind, desto enger ist der Umfang der Typdefinition. Sie können sich am folgenden Beispiel orientieren:

Typ Ergebnis4 = { a: wahr, b: falsch } erweitert { a: wahr } ? wahr : falsch // wahr

Verwenden bedingter Typen in generischen Typen

Betrachten Sie die folgende Demotypdefinition:

Typ Demo<T, U> = T erweitert U? nie : T

In Kombination mit den in der bedingten Beurteilung verwendeten Erweiterungen können wir wissen, dass „a“ | „b“ | „c“ „a“ erweitert, also ist das Ergebnis von Demo<„a“ | „b“ | „c“, „a“> „a“ | „b“ | „c“?
Schauen Sie auf der offiziellen Website nach, auf der Folgendes erwähnt wird:

Wenn bedingte Typen auf einen generischen Typ einwirken, werden sie distributiv, wenn ihnen ein Union-Typ zugewiesen wird.

Das heißt, wenn der bedingte Typ auf einen generischen Typ einwirkt, wird der Union-Typ aufgeteilt und verwendet. Das bedeutet, Demo<'a' | 'b' | 'c', 'a'> wird aufgeteilt in 'a' erweitert 'a', 'b' erweitert 'a', 'c' erweitert 'a'. Im Pseudocode sieht es ähnlich aus wie:

Funktion Demo(T, U) {
  return T.map(val => {
    wenn (Wert !== U) returniere Wert
    gib „niemals“ zurück
  })
}

Demo(['a', 'b', 'c'], 'a') // ['nie', 'b', 'c']

Darüber hinaus gilt gemäß der Definition des Typs „never“: Der Typ „never“ kann jedem Typ zugewiesen werden, aber kein Typ kann „never“ zugewiesen werden (außer „never“ selbst). Das heißt, niemals ist | 'b' | 'c' gleichbedeutend mit 'b' | 'c'.

Daher ist das Ergebnis von Demo<'a' | 'b' | 'c', 'a'> nicht 'a' | 'b' | 'c', sondern 'b' | 'c'.

Werkzeugtyp

Aufmerksame Leser haben möglicherweise festgestellt, dass der Deklarationsprozess des Demo-Typs tatsächlich das Implementierungsprinzip von Exclude<Type, ExcludedUnion> im offiziell von TypeScript bereitgestellten Tool-Typ ist, das verwendet wird, um den Union-Typ ExcludedUnion vom Type-Typ auszuschließen.

Typ T = Demo<'a' | 'b' | 'c', 'a'> // T: 'b' | 'c'

Basierend auf der Demo-Typdefinition können Sie Omit<Type, Keys> weiter im offiziellen Tooltyp implementieren, der zum Entfernen des Objekttyps verwendet wird
Der Attributwert, der dem Schlüsseltyp entspricht.

Typ Omit<Typ, Schlüssel> = {
  [P in Demo<keyof Typ, Schlüssel>]: Typ<P>
}

Schnittstelle Todo {
  Titel: Zeichenfolge;
  Beschreibung: Zeichenfolge;
  abgeschlossen: Boolesch;
}

Typ T = Omit<Todo, 'Beschreibung'> // T: { Titel: Zeichenfolge; abgeschlossen: Boolescher Wert }

Rettungskapsel

Wenn Sie möchten, dass das Ergebnis von Demo<'a' | 'b' | 'c', 'a'> 'a' | 'b' | 'c' ist, ist das möglich? Laut der Beschreibung auf der offiziellen Website:

Normalerweise ist Distributivität das gewünschte Verhalten. Um dieses Verhalten zu vermeiden, können Sie jede Seite des Schlüsselworts extends mit eckigen Klammern umgeben.

Wenn Sie nicht jeden Typ im Generikum durchlaufen möchten, können Sie das Generikum in eckige Klammern einschließen, um den gesamten Teil anzugeben, der das Generikum verwendet.
Typ Demo<T, U> = [T] erweitert [U]? nie : T

Typ Demo<T, U> = [T] erweitert [U]? nie : T

// Ergebnis ist vom Typ 'a' | 'b' | 'c'
Typergebnis = Demo<'a' | 'b' | 'c', 'a'>

Verwenden von bedingten Typen in Pfeilfunktionen

Bei der Verwendung ternärer Ausdrücke in Pfeilfunktionen führt die Lesegewohnheit von links nach rechts dazu, dass der Funktionsinhaltsbereich verwirrend wird, wenn er nicht in Klammern eingeschlossen ist. Ist x im folgenden Code beispielsweise ein Funktionstyp oder ein Boolescher Typ?

// Die Absicht ist nicht klar.
var x = a => 1 ? wahr : falsch

In der Eslint-Regel „no-confusing-arrow“ wird Folgendes empfohlen:

var x = a => (1 ? wahr : falsch)

Wenn in TypeScript-Typdefinitionen extends in Pfeilfunktionen verwendet wird, gilt das Gleiche. Aufgrund der Lesegewohnheit von links nach rechts können Leser hinsichtlich der Ausführungsreihenfolge von Typcodes verwirrt sein.

Typ Curry<P erweitert beliebig[], ​​R> =
  (Argument: Head<P>) => HasTail<P> erweitert true? Curry<Tail<P>, R>: R

Daher wird empfohlen, bei der Verwendung von Erweiterungen in Pfeilfunktionen Klammern hinzuzufügen, was bei der Codeüberprüfung sehr hilfreich ist.

Typ Curry<P erweitert beliebig[], ​​R> =
  (Argument: Head<P>) => (HasTail<P> erweitert true? Curry<Tail<P>, R>: R)

Verwenden bedingter Typen mit Typinferenz

In TypeScript wird die Type-Infer-Syntax normalerweise in Verbindung mit Extended verwendet. Verwenden Sie es, um Typen automatisch abzuleiten. Damit lässt sich beispielsweise der Tooltyp ReturnType<Type> implementieren, der zur Rückgabe des Rückgabetyps der Funktion Type dient.
Typ ReturnType<T erweitert Funktion> = T erweitert (...Argumente: beliebig) => folgere U? U: nie

Typ ReturnType<T erweitert Funktion> = T erweitert (...Argumente: beliebig) => folgere U? U: nie

MyReturnType<() => string> // Zeichenfolge
MyReturnType<() => Versprechen<boolean> // Versprechen<boolean>

Durch die Kombination von Erweiterungen mit Typinferenz können auch arraybezogene Tooltypen wie Pop<T>, Shift<T> und Reverse<T> implementiert werden.

Pop<T>:

Typ Pop<T erweitert beliebig[]> = T erweitert [...schließe ExceptLast, beliebig] ? ExceptLast : nie

Typ T = Pop<[3, 2, 1]> // T: [3, 2]

Umschalt<T>:

Typ Shift<T erweitert any[]> = T erweitert [infer _, ...infer O] ? O : nie

Typ T = Umschalt<[3, 2, 1]> // T: [2, 1]

Umgekehrt<T>

Typ Reverse<T> = T erweitert [folgert aus F, ...folgert aus Anderen]
  ? [...Umgekehrt<Andere>, F]
  : []

Typ T = Reverse<['a', 'b']> // T: ['b', 'a']

Verwenden Sie bedingte Typen, um zu bestimmen, ob zwei Typen völlig gleich sind

Wir können auch bedingte Typen verwenden, um zu bestimmen, ob die Typen A und B völlig gleich sind. Derzeit gibt es in der Community zwei Hauptlösungen:

Lösung 1: Siehe Problem.

Exporttyp Equal1<T, S> =
  [T] erweitert [S] ? (
    [S] erweitert [T] ? true : false
  ) : FALSCH

Der einzige Nachteil dieser Lösung besteht derzeit darin, dass sie jeden Typ als jedem anderen Typ gleichwertig beurteilt.

Typ T = Gleich1<{x:beliebig}, {x:Zahl}> // T: wahr

Lösung 2: Siehe Problem.

Exporttyp Equal2<X, Y> =
  (<T>() => T erweitert X ? 1 : 2) erweitert
  (<U>() => U erweitert Y ? 1 : 2) ? wahr : falsch

Der einzige Nachteil dieser Lösung besteht darin, dass sie einige Mängel bei der Handhabung von Schnittpunkttypen aufweist.

Typ T = Equal2<{x:1} & {y:2}, {x:1, y:2}> // falsch

Zu den beiden oben genannten Methoden zur Beurteilung, ob Typen gleich sind, gibt es unterschiedliche Meinungen. Der Autor wirft hier lediglich einige Ideen ein, um eine Diskussion anzuregen.

Zusammenfassen

Damit ist dieser Artikel über das intensive Lesen und Üben von bedingten Typen in TypeScript abgeschlossen. Weitere relevante Inhalte zu bedingten Typen in TypeScript finden Sie in früheren Artikeln auf 123WORDPRESS.COM oder in den folgenden verwandten Artikeln. Ich hoffe, dass jeder 123WORDPRESS.COM in Zukunft unterstützen wird!

Das könnte Sie auch interessieren:
  • Grundlagen und Beispiele zur TypeScript-Aufzählung
  • Typescript+React zum Erzielen einfacher Drag-and-Drop-Effekte auf Mobilgeräten und PCs
  • TypeScript-Problem beim Iterieren über Objekteigenschaften

<<:  6 Lösungen für die Unfähigkeit von IDEA, eine Verbindung zur MySQL-Datenbank herzustellen

>>:  Detaillierte Schritte zur Installation von Nginx unter Linux

Artikel empfehlen

Linux verwendet stty zum Anzeigen und Ändern von Terminalzeileneinstellungen

Sttty ist ein gängiger Befehl zum Ändern und Druc...

Transkript der Implementierung berechneter Vue-Eigenschaften

In diesem Artikel wird das Implementierungszeugni...

Ladeanimation mit CSS3 implementiert

Ergebnisse erzielen Implementierungscode <h1&g...

Hilfe zum Webdesign: Datenreferenz für Web-Schriftgrößen

<br />Der Inhalt wurde aus dem Internet repr...

So importieren Sie Vue-Komponenten automatisch bei Bedarf

Inhaltsverzeichnis Globale Registrierung Teilregi...

Stabile Version von MySQL 8.0.18 veröffentlicht! Hash Join ist wie erwartet da

Die stabile Version (GA) von MySQL 8.0.18 wurde g...

So ändern Sie die Zeichensatzkodierung in MySQL 5.5/5.6 unter Linux auf UTF8

1. Melden Sie sich bei MySQL an und verwenden Sie...

Miniprogramm zur Implementierung der Sieve-Lotterie

In diesem Artikelbeispiel wird der spezifische Co...

Beispiel für die MySQL-Volltext-Fuzzy-Suche nach der Methode MATCH AGAINST

MySQL 4.x und höher bieten Unterstützung für die ...

Designtheorie: Lesbarkeit und Verständlichkeit von Texten

<br />Vor nicht allzu langer Zeit habe ich a...

Analyse des MySQL-Sperrmechanismus und der Verwendung

Dieser Artikel veranschaulicht anhand von Beispie...