ÜberblickIn TypeScript verwenden wir Generika, um die relevanten Funktionstypen einzuschränken. Die Funktionen schließen hier auch den Konstruktor der Klasse mit ein, so dass der Deklarationsteil einer Klasse auch Generika verwenden kann. Also, was genau sind Generika? Was wäre, wenn wir Generika auf einfache Weise verstehen würden? Was sind GenerikaAls Generika werden Funktionen bezeichnet, bei denen bei der Definition einer Funktion, Schnittstelle oder Klasse nicht vorab ein bestimmter Typ festgelegt wird, sondern der Typ bei der Verwendung angegeben wird. Einfach ausgedrückt sind Generika „Parameter“ im Typsystem und ihre Hauptfunktion besteht in der Wiederverwendung von Typen. Wie aus der obigen Definition ersichtlich ist, wird es nur in Funktionen, Schnittstellen und Klassen verwendet. Es unterscheidet sich von den Funktionsparametern im JS-Programm (obwohl die Bedeutung dieselbe ist), da Typescript ein statisches Typsystem ist, das beim Kompilieren von JS eine Typprüfung durchführt. Daher werden generische Parameter tatsächlich zur Laufzeit während des Kompilierungsprozesses verwendet. Er wird als „Parameter“ bezeichnet, da er genau dieselben Eigenschaften wie ein Funktionsparameter aufweist. Funktion erhöhen(Param) { // ... } Im Typsystem verwenden wir Generika wie diese: Funktion erhöhen<T>(param: T): T { //... } Wenn Param ein Typ ist, wird T diesem Typ zugewiesen und im Rückgabewert ist T zur Typprüfung von diesem Typ. System erstellenSie sollten wissen, dass das Typsystem von Typescript selbst ebenfalls programmiert werden muss, seine Programmiermethode jedoch seltsam ist: Sie müssen JS-Code in seinen Programmcode einstreuen (die Aussage, dass JS-Code in TS-Code eingestreut wird, ist seltsam, da unser intuitives Gefühl ist, dass TS-Code in JS-Code eingemischt ist). Eine der wichtigsten Formen in der Programmierung ist die Funktion. Haben Sie bei der Typprogrammierung in Typescript Funktionen gesehen? NEIN. Dies liegt daran, dass dort, wo es Generika gibt, auch Funktionen vorhanden sind, die Form der Funktion jedoch durch den JS-Code aufgeteilt wird. Um das Endprodukt zu erhalten, muss Typescript kompiliert werden. Während des Kompilierungsprozesses müssen zwei Dinge getan werden. Erstens muss der Typprogrammierungscode im Speicher ausgeführt werden, um ein Typprüfungssystem zu bilden. Das heißt, wir können den JS-Code typprüfen. Erstens erhält der Typescript-Compiler nach dem Ausführen des TS-Programmierungscodes ein Laufzeitprüfungssystem. Dieser Artikel stammt aus dem Podcast von Fei Zige und führt dieses System aus, um Typzusicherungen für den darin eingestreuten JS-Code durchzuführen; zweitens muss JS ausgegeben werden. Während des Ausgabeprozesses hat das Kompilierungssystem den Typprogrammierungscode ausgeführt, genau wie Echo-JS-Code in PHP-Code. Der PHP-Code wurde ausgeführt und was angezeigt wird, ist JS-Code. Wenn Sie TypeScript aus dieser Perspektive betrachten, können Sie möglicherweise besser verstehen, warum es als Obermenge von JavaScript bezeichnet wird und warum das kompilierte Ergebnis JS ist. Allgemeines Verständnis von GenerikaNachdem wir nun die Logik des TS-Kompilierungssystems verstehen, können wir die Typprogrammierung emotional von der Geschäftsprogrammierung von JS selbst unterscheiden. Die „Generika“, von denen wir sprechen, existieren nur im Teil der Typprogrammierung, also im kompilierten Laufzeitcode von ts. Schauen wir uns ein einfaches Beispiel an: Funktion erhöhen<T>(param: T): T { //... } Was würde passieren, wenn wir den JS-Code von diesem Code trennen und dann einen Typbeschreibungstext zur Darstellung verwenden würden? //Funktion @type deklarieren, Parameter ist T, Rückgabeergebnis ist (T): T @type = T => (T): T //Führen Sie die Funktion aus, um einen Typ F zu erhalten, der vom Typ (Zahl) ist: Zahl @F = @Typ(Zahl) // Erfordert, dass die Erhöhungsfunktion dem F-Typ entspricht, d. h. der Parameter ist eine Zahl und der Rückgabewert ist ebenfalls eine Zahl @@F Funktion erhöhen(Param) { // ... } @@Ende Eigentlich gibt es keine Syntax wie @@F. Ich habe sie erfunden, damit Sie das Typsystem aus einer anderen Perspektive betrachten können. Wenn wir erst einmal verstanden haben, dass Generika eine Art „Parameter“ sind, können wir fragen: Wo liegt die Funktion des Typsystems? Bei JS-Funktionen können Sie problemlos auf die Funktionsdeklarationsanweisung und die Parameter hinweisen, in TS ist dieser Teil jedoch ausgeblendet. In einigen spezifischen Strukturen können wir jedoch leicht den Schatten von Typfunktionen erkennen: // Deklarieren Sie eine generische Schnittstelle. Dies wird genauso geschrieben wie das Deklarieren einer Funktion. Wir verwenden die beschreibende Sprache, um es zu beschreiben. @type = T => (T): T Schnittstelle GenericIdentityFn<T> { (Argument: T): T; } // Diese Schreibweise ähnelt ein wenig einer Closure-Funktion. Nach der Deklaration der Funktion wird diese sofort ausgeführt. Beschreibungssprache: @@[T => (T): T](any) Funktion Identität<T>(Argument: T): T { Argument zurückgeben; } // Die Verwendung einer generischen Schnittstelle ist wie das Aufrufen einer Funktion. Wir verwenden eine beschreibende Sprache, um @type(number) zu beschreiben. let myIdentity: GenericIdentityFn<Nummer> = Identität; Schreiben wir den gesamten obigen Code unter Verwendung des Beschreibungstextes neu: @GenericIdentityFn = T => (T): T @@[T => (T): T](beliebig) Funktion identifizieren(arg) { Rückgabeargument } @@Ende @@GenericIdentityFn(Zahl) let myIdentity = Identität @@Ende Wir deklarieren zwei Funktionen im Typsystem, @GenericIdentityFn und @some (anonyme Funktion @[T => (T): T]). Obwohl es sich um zwei Funktionen handelt, sind sie tatsächlich genau gleich, da TypeScript ein Strukturtyp ist, d. h. bei der Typprüfung wird nur bestimmt, ob der Typ jedes Knotens in der Struktur derselbe ist, und der Zeiger der Typvariablen selbst muss nicht gleich bleiben. @GenericIdentityFn und @some werden aufgerufen, um identify bzw. myIdentify zu ändern. Beim Aufruf erhalten sie unterschiedliche Parameter, sodass die endgültigen Typprüfungsregeln unterschiedlich sind. Identify muss nur sicherstellen, dass die Parameter- und Rückgabewerttypen identisch sind. Für den spezifischen Typ wird any verwendet. myIdentify stellt nicht nur sicher, dass der Typ des Parameterrückgabewerts derselbe ist, sondern erfordert auch, dass der Typ eine Zahl sein muss. Generische KlassenNeben generischen Schnittstellen können Klassen auch verallgemeinert werden, d. h. „generische Klassen“. Lassen Sie uns mithilfe generischer Klassen die Schritte zum Deklarieren und Verwenden von Generika untersuchen. Klasse GenericNumber<T> { Nullwert: T; hinzufügen: (x: T, y: T) => T; } let meineGenericNumber = neue GenericNumber<Nummer>(); Die generische Schnittstelle im vorherigen Artikel wird wie eine Funktion geschrieben, da sie nur dazu dient, den Typ der Funktion einzuschränken. Tatsächlich können wir eine generische Schnittstelle und eine generische Klasse mithilfe einer Beschreibungssprache neu beschreiben. Wir verwenden eine beschreibende Sprache, um den roten Teil oben zu beschreiben: @GenericNumber = T => Klasse { Nullwert: T; hinzufügen: (x: T, y: T) => T; } Die Funktion @GenericNumber verwendet T als Parameter und gibt eine Klasse zurück. Der Parameter T wird im Funktionskörper von @type mehrfach verwendet. @GenericIdentityFn = T => Schnittstelle { (Argument: T): T; } Wir beschreiben die vorherige Schnittstelle GenericIdentityFn neu, damit wir der Schnittstelle weitere Methoden hinzufügen können. Es fällt auf, dass selbst nachdem die integrierten Basistypen von Typescript, wie z. B. Array, als generische Schnittstellen und generische Klassen deklariert wurden, diese Schnittstellen und Klassen bei Verwendung Parameter über <> übergeben müssen. Im Wesentlichen handelt es sich bei ihnen alle um Funktionen, sie haben nur unterschiedliche Rückgabewerte. Andere beliebte Erklärungen zur generischen VerwendungAls nächstes müssen wir einen komplexen Typ beschreiben: Klasse Tier { numLegs: Zahl; } Funktion erstelleInstanz<A erweitert Tier>(c: neu () => A): A { gib ein neues c() zurück; } Lassen wir den Teil new() zunächst außen vor, sondern betrachten wir die extends Syntax in den spitzen Klammern. Wie ist diese zu verstehen? Tatsächlich stellt sich für uns die Frage, wann zur Kompilierungszeit der Inhalt in den spitzen Klammern von <A extends Animal> ausgeführt wird, davor oder dazwischen? // @type = (A erweitert Animal) => (new() => A): A @type(T) // Immer noch @type = A => (new() => A): A @type(T erweitert Tier) Da TypeScript ein statisches Typsystem und Animal eine unveränderliche Klasse ist, kann davon ausgegangen werden, dass der Inhalt der spitzen Klammern ausgeführt wurde, bevor die Klasse erstellt wurde. @type = (A erweitert Tier) => (neu() => A): A Das heißt, um mit @type(T) einen Typ zu generieren, muss T zunächst die Struktur von Animal erfüllen, dann kann der gewünschte Typ erhalten werden. Wenn T die Struktur der Klasse Animal nicht mehr erfüllt, meldet der Compiler direkt einen Fehler. Dieser Fehler tritt nicht in der Typprüfungsphase auf, sondern in der Erstellungsphase des Typsystems, also in der Ausführungsphase des TS-Codes. Diese Situation wird als „generische Einschränkung“ bezeichnet. Darüber hinaus ist eine Syntax wie <A,B> tatsächlich dasselbe wie bei Funktionsparametern. @type = (A, B) => (A|B): IrgendeinTyp Schauen wir uns den eingebauten Basistyp von ts an: Array<number> @Array = beliebig => beliebig[] AbschlussGenerika in Typescript sind eigentlich Parameter von Typgenerierungsfunktionen. Die Inhalte dieses Artikels sind alle frei erfunden und eignen sich nur zur Ideenfindung beim Verständnis von ts. Für echtes Programmieren sind sie nicht geeignet. Dies wird hiermit erklärt. Oben werden TypeScript-Generika im Detail erklärt. Weitere Informationen zu TypeScript-Generika finden Sie in den anderen verwandten Artikeln auf 123WORDPRESS.COM! Das könnte Sie auch interessieren:
|
<<: Installationsschritte von MySQL unter Linux
In diesem Artikel wird der spezifische Code von J...
Inhaltsverzeichnis Hintergrund So ermitteln Sie, ...
1. Daten initialisieren Tabelle löschen, wenn `te...
In letzter Zeit stoße ich bei der Verwendung von ...
Mit der kontinuierlichen Entwicklung der Internetw...
Erstellen Sie einen MySQL-Benutzer und autorisier...
Mac wird mit Apache-Umgebung geliefert Öffnen Sie...
Die Vue-Routing-Seite this.route.push wird nicht ...
Inhaltsverzeichnis 1. Komponentenaufblähung 2. Än...
1. Gehen Sie zunächst auf die offizielle Website,...
Wenn wir SQL zum Extrahieren von Daten verwenden,...
Vorwort Lassen Sie mich Ihnen zeigen, wie ich ein...
1. Testumgebung Name Version centos 7.6 Docker 18...
Inhaltsverzeichnis 2. Bewährte Methoden 2.1 Am Le...
Daten initialisieren Tabelle löschen, wenn `test_...