"Si un ouvrier veut bien faire son travail, il doit d'abord affûter ses outils." - Confucius, "Les Entretiens de Confucius. Lu Linggong"
Page de garde > La programmation > Maîtriser TypeScript : Comprendre la puissance des extensions

Maîtriser TypeScript : Comprendre la puissance des extensions

Publié le 2024-11-06
Parcourir:439

Mastering TypeScript: Understanding the Power of extends

Le mot-clé extends dans TypeScript est une sorte de couteau suisse. Il est utilisé dans plusieurs contextes, notamment l'héritage, les génériques et les types conditionnels. Comprendre comment utiliser efficacement extends peut conduire à un code plus robuste, réutilisable et de type sécurisé.

Héritage à l'aide d'extensions

L'une des principales utilisations des extensions est l'héritage, vous permettant de créer de nouvelles interfaces ou classes qui s'appuient sur celles existantes.

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"
};

Dans cet exemple, StaffUser étend User, héritant de toutes ses propriétés et en ajoutant de nouvelles. Cela nous permet de créer des types plus spécifiques basés sur des types plus généraux.

Héritage de classe

Le mot-clé extends est également utilisé pour l'héritage de classe :

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!

Ici, Dog étend Animal, en héritant de ses propriétés et méthodes, et en ajoutant également les siennes.

Contraintes de type dans les génériques

Le mot-clé extends est crucial lorsque l'on travaille avec des génériques, car il nous permet de limiter les types pouvant être utilisés avec une fonction ou une classe générique.

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. interface Printable : Ici, nous définissons une interface nommée Printable. Cette interface déclare un contrat auquel toute classe l'implémentant doit adhérer. Le contrat spécifie que toute classe implémentant Printable doit fournir une méthode nommée print qui ne prend aucun argument et renvoie void
  2. function printObject(obj: T) : Il s'agit d'une fonction générique nommée printObject. Il prend un seul argument nommé obj, qui est de type T. Le paramètre de type T est limité aux types qui étendent (implémentent) l'interface imprimable et peuvent être utilisés comme argument de cette fonction.
  3. la classe Book implémente Printable et la classe Magazine implémente Printable : ici, nous définissons deux classes, Book et Magazine, qui implémentent toutes deux l'interface Printable. Cela signifie que ces classes doivent fournir une méthode d'impression comme l'exige le contrat de l'interface Printable.
  4. const monLivre = nouveau Livre(); et const myMagazine = new Magazine(); : Nous créons des instances des classes Book et Magazine.
  5. printObject(monLivre); et printObject(myMagazine); : Nous appelons la fonction printObject avec les instances de Book et Magazine. Étant donné que les classes Book et Magazine implémentent l’interface Printable, elles remplissent la contrainte du paramètre de type T extends Printable. À l'intérieur de la fonction, la méthode d'impression de la classe appropriée est appelée, ce qui donne le résultat attendu.
  6. // printObject(42); : Si nous essayons d'appeler printObject avec un type qui n'implémente pas l'interface Printable, comme le nombre 42, TypeScript générera une erreur. En effet, la contrainte de type n'est pas satisfaite, car number n'a pas de méthode d'impression comme l'exige l'interface Printable.

En résumé, le mot-clé extends dans le contexte de la fonction printObject(obj: T) est utilisé pour garantir que le type T utilisé comme argument adhère au contrat défini par l'interface Printable. Cela garantit que seuls les types dotés d'une méthode d'impression peuvent être utilisés avec la fonction printObject, appliquant ainsi un comportement et un contrat spécifiques pour l'utilisation de la fonction.

Types conditionnels

T extends U ? X : Y
  • T est le type en cours de vérification
  • U est le type de condition par rapport auquel T est vérifié.
  • X est le type auquel le type conditionnel est évalué si T étend (est attribuable à) U
  • Y est le type auquel le type conditionnel est évalué si T n'étend pas U
type ExtractNumber = T extends number ? T : never;

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

Ici, le type ExtractNumber prend un paramètre de type T. Le type conditionnel vérifie si T étend le type numérique. si tel est le cas, le type est résolu en T (qui est le type numérique). Si ce n'est pas le cas, le type est résolu comme jamais.

Le mot-clé extends avec les types d’union

Maintenant, considérons l'expression A | B | C étend A. Cela peut sembler contre-intuitif au début, mais dans TypeScript, cette condition est en réalité fausse. Voici pourquoi :

  1. Dans TypeScript, lorsque vous utilisez extends avec un type d'union sur le côté gauche, cela équivaut à demander : "Tous les types possibles de cette union sont-ils attribuables au type de droite ?"
  2. En d’autres termes, A | B | C étend A demande : "A peut-il être affecté à A, ET B peut-il être affecté à A, ET C peut-il être affecté à A ?"
  3. Bien que A puisse certainement être attribué à A, B et C peuvent ne pas être attribuables à A (à moins qu'ils ne soient des sous-types de A), le résultat global est donc faux.
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

Dans cet exemple, IsCitrus est faux car tous les fruits de l'union Fruit ne sont pas des Agrumes.

Meilleures pratiques et conseils

  • L'utilisation s'étend pour les relations significatives : utilisez l'héritage uniquement lorsqu'il existe une relation claire "est-une" entre les types.
  • Préférez la composition à l'héritage : dans de nombreux cas, la composition (utilisant des interfaces et des intersections de types) peut être plus flexible que l'héritage de classe.
  • Soyez prudent avec les chaînes d'héritage profondes : l'héritage profond peut rendre le code plus difficile à comprendre et à maintenir.
  • Exploitez les types conditionnels pour les API flexibles : utilisez des types conditionnels avec des extensions pour créer des API qui s'adaptent en fonction des types d'entrée.
  • L'utilisation s'étend aux génériques pour créer des fonctions réutilisables et sécurisées : cela vous permet d'écrire des fonctions qui fonctionnent avec une variété de types tout en conservant la sécurité des types
Déclaration de sortie Cet article est reproduit sur : https://dev.to/hasanm95/mastering-typescript-understanding-the-power-of-extends-1n2o?1 En cas de violation, veuillez contacter [email protected] pour le supprimer.
Dernier tutoriel Plus>

Clause de non-responsabilité: Toutes les ressources fournies proviennent en partie d'Internet. En cas de violation de vos droits d'auteur ou d'autres droits et intérêts, veuillez expliquer les raisons détaillées et fournir une preuve du droit d'auteur ou des droits et intérêts, puis l'envoyer à l'adresse e-mail : [email protected]. Nous nous en occuperons pour vous dans les plus brefs délais.

Copyright© 2022 湘ICP备2022001581号-3