„Wenn ein Arbeiter seine Arbeit gut machen will, muss er zuerst seine Werkzeuge schärfen.“ – Konfuzius, „Die Gespräche des Konfuzius. Lu Linggong“
Titelseite > Programmierung > TypeScript beherrschen: Die Leistungsfähigkeit von Extends verstehen

TypeScript beherrschen: Die Leistungsfähigkeit von Extends verstehen

Veröffentlicht am 06.11.2024
Durchsuche:609

Mastering TypeScript: Understanding the Power of extends

Das Schlüsselwort „extens“ in TypeScript ist eine Art Schweizer Taschenmesser. Es wird in mehreren Kontexten verwendet, einschließlich Vererbung, Generika und bedingten Typen. Wenn Sie verstehen, wie Sie Erweiterungen effektiv nutzen, können Sie robusteren, wiederverwendbareren und typsichereren Code erstellen.

Vererbung mit Extends

Eine der Hauptanwendungen von Erweiterungen ist die Vererbung, die es Ihnen ermöglicht, neue Schnittstellen oder Klassen zu erstellen, die auf vorhandenen aufbauen.

interface User {
  firstName: string;
  lastName: string;
  email: string;
}

interface StaffUser extends User {
  roles: string[];
  department: string;
}

const regularUser: User = {
  firstName: "John",
  lastName: "Doe",
  email: "[email protected]"
};

const staffMember: StaffUser = {
  firstName: "Jane",
  lastName: "Smith",
  email: "[email protected]",
  roles: ["Manager", "Developer"],
  department: "Engineering"
};

In diesem Beispiel erweitert StaffUser den Benutzer, erbt alle seine Eigenschaften und fügt neue hinzu. Dadurch können wir spezifischere Typen basierend auf allgemeineren erstellen.

Klassenvererbung

Das Schlüsselwort „extends“ wird auch für die Klassenvererbung verwendet:

class Animal {
  constructor(public name: string) {}

  makeSound(): void {
    console.log("Some generic animal sound");
  }
}

class Dog extends Animal {
  constructor(name: string, public breed: string) {
    super(name);
  }

  makeSound(): void {
    console.log("Woof! Woof!");
  }

  fetch(): void {
    console.log(`${this.name} is fetching the ball!`);
  }
}

const myDog = new Dog("Buddy", "Golden Retriever");
myDog.makeSound(); // Output: Woof! Woof!
myDog.fetch(); // Output: Buddy is fetching the ball!

Hier erweitert Dog Animal, erbt dessen Eigenschaften und Methoden und fügt auch eigene hinzu.

Typbeschränkungen in Generics

Das Schlüsselwort „extens“ ist bei der Arbeit mit Generika von entscheidender Bedeutung, da es uns ermöglicht, die Typen einzuschränken, die mit einer generischen Funktion oder Klasse verwendet werden können.

interface Printable {
  print(): void;
}

function printObject(obj: T) {
  obj.print();
}

class Book implements Printable {
  print() {
    console.log("Printing a book.");
  }
}

class Magazine implements Printable {
  print() {
    console.log("Printing a magazine.");
  }
}

const myBook = new Book();
const myMagazine = new Magazine();

printObject(myBook);      // Output: Printing a book.
printObject(myMagazine);  // Output: Printing a magazine.
// printObject(42);       // Error, number doesn't have a 'print' method
  1. Schnittstelle Printable: Hier definieren wir eine Schnittstelle namens Printable. Diese Schnittstelle deklariert einen Vertrag, den jede Klasse, die sie implementiert, einhalten muss. Der Vertrag legt fest, dass jede Klasse, die Printable implementiert, eine Methode namens print bereitstellen muss, die keine Argumente akzeptiert und void zurückgibt
  2. Funktion printObject(obj: T): Dies ist eine generische Funktion namens printObject. Es benötigt ein einzelnes Argument namens obj, das vom Typ T ist. Der Typparameter T ist auf Typen beschränkt, die die Printable-Schnittstelle erweitern (implementieren) und als Argument für diese Funktion verwendet werden können.
  3. Die Klasse Book implementiert Printable und die Klasse Magazine implementiert Printable: Hier definieren wir zwei Klassen, Book und Magazine, die beide die Printable-Schnittstelle implementieren. Dies bedeutet, dass diese Klassen eine Druckmethode bereitstellen müssen, wie im Vertrag der Printable-Schnittstelle erforderlich.
  4. const myBook = new Book(); und const myMagazine = new Magazine();: Wir erstellen Instanzen der Klassen Book und Magazine.
  5. printObject(myBook); und printObject(myMagazine);: Wir rufen die printObject-Funktion mit den Instanzen von Book und Magazine auf. Da sowohl die Buch- als auch die Magazinklasse die Schnittstelle „Druckbar“ implementieren, erfüllen sie die Einschränkung des Typparameters „T erweitert Druckbar“. Innerhalb der Funktion wird die Druckmethode der entsprechenden Klasse aufgerufen, was zur erwarteten Ausgabe führt.
  6. // printObject(42);: Wenn wir versuchen, printObject mit einem Typ aufzurufen, der die Printable-Schnittstelle nicht implementiert, wie etwa die Zahl 42, löst TypeScript einen Fehler aus. Dies liegt daran, dass die Typbeschränkung nicht erfüllt ist, da number nicht über eine Druckmethode verfügt, wie sie von der Printable-Schnittstelle gefordert wird.

Zusammenfassend lässt sich sagen, dass das Schlüsselwort „extens“ im Kontext der Funktion printObject(obj: T) verwendet wird, um sicherzustellen, dass der als Argument verwendete Typ T dem von der Printable-Schnittstelle definierten Vertrag entspricht. Dadurch wird sichergestellt, dass nur Typen mit einer Druckmethode mit der printObject-Funktion verwendet werden können, wodurch ein bestimmtes Verhalten und ein bestimmter Vertrag für die Verwendung der Funktion erzwungen werden.

Bedingte Typen

T extends U ? X : Y
  • T ist der Typ, der überprüft wird
  • U ist der Bedingungstyp, gegen den T geprüft wird.
  • X ist der Typ, zu dem der bedingte Typ ausgewertet wird, wenn T U erweitert (zuweisbar ist).
  • Y ist der Typ, zu dem der bedingte Typ ausgewertet wird, wenn T U nicht erweitert
type ExtractNumber = T extends number ? T : never;

type NumberOrNever = ExtractNumber; // number
type StringOrNever = ExtractNumber; // never

Hier akzeptiert der ExtractNumber-Typ einen Typparameter T. Der bedingte Typ prüft, ob T den Zahlentyp erweitert. Wenn dies der Fall ist, wird der Typ in T aufgelöst (das ist der Zahlentyp). Ist dies nicht der Fall, wird der Typ in „nie“ aufgelöst.

Das Schlüsselwort „extends“ mit Union-Typen

Betrachten wir nun den Ausdruck A | B | C erweitert A. Dies mag zunächst kontraintuitiv erscheinen, aber in TypeScript ist diese Bedingung tatsächlich falsch. Hier ist der Grund:

  1. Wenn Sie in TypeScript Extends mit einem Union-Typ auf der linken Seite verwenden, entspricht dies der Frage: „Ist jeder mögliche Typ in dieser Union dem Typ auf der rechten Seite zuweisbar?“
  2. Mit anderen Worten, A | B | C erweitert A fragt: „Kann A A zugewiesen werden, UND kann B A zugewiesen werden, UND kann C A zugewiesen werden?“
  3. Während A sicherlich A zugeordnet werden kann, sind B und C möglicherweise nicht A zuordenbar (es sei denn, sie sind Untertypen von A), sodass das Gesamtergebnis falsch ist.
type Fruit = "apple" | "banana" | "cherry";
type CitrusFruit = "lemon" | "orange";

type IsCitrus = T extends CitrusFruit ? true : false;

type Test1 = IsCitrus; // true
type Test2 = IsCitrus; // false
type Test3 = IsCitrus; // false

In diesem Beispiel ist IsCitrus falsch, da nicht alle Früchte in der Fruit-Union CitrusFruit sind.

Best Practices und Tipps

  • Erweiterungen für sinnvolle Beziehungen verwenden: Vererbung nur verwenden, wenn zwischen Typen eine klare "Ist-ein"-Beziehung besteht.
  • Komposition gegenüber Vererbung bevorzugen: In vielen Fällen kann die Komposition (unter Verwendung von Schnittstellen und Typschnittpunkten) flexibler sein als die Klassenvererbung.
  • Seien Sie vorsichtig bei tiefen Vererbungsketten: Tiefe Vererbung kann das Verständnis und die Wartung von Code erschweren.
  • Bedingte Typen für flexible APIs nutzen: Verwenden Sie bedingte Typen mit Erweiterungen, um APIs zu erstellen, die sich basierend auf Eingabetypen anpassen.
  • Verwenden Sie Erweiterungen in Generika, um wiederverwendbare, typsichere Funktionen zu erstellen: Dadurch können Sie Funktionen schreiben, die mit einer Vielzahl von Typen funktionieren und gleichzeitig die Typsicherheit beibehalten
Freigabeerklärung Dieser Artikel ist abgedruckt unter: https://dev.to/hasanm95/mastering-typescript-understanding-the-power-of-extends-1n2o?1 Bei Verstößen wenden Sie sich bitte an [email protected], um ihn zu löschen
Neuestes Tutorial Mehr>

Haftungsausschluss: Alle bereitgestellten Ressourcen stammen teilweise aus dem Internet. Wenn eine Verletzung Ihres Urheberrechts oder anderer Rechte und Interessen vorliegt, erläutern Sie bitte die detaillierten Gründe und legen Sie einen Nachweis des Urheberrechts oder Ihrer Rechte und Interessen vor und senden Sie ihn dann an die E-Mail-Adresse: [email protected] Wir werden die Angelegenheit so schnell wie möglich für Sie erledigen.

Copyright© 2022 湘ICP备2022001581号-3