"Si un trabajador quiere hacer bien su trabajo, primero debe afilar sus herramientas." - Confucio, "Las Analectas de Confucio. Lu Linggong"
Página delantera > Programación > Dominar TypeScript: comprender el poder de las extensiones

Dominar TypeScript: comprender el poder de las extensiones

Publicado el 2024-11-06
Navegar:483

Mastering TypeScript: Understanding the Power of extends

La palabra clave extends en TypeScript es una especie de navaja suiza. Se utiliza en múltiples contextos, incluidos herencia, genéricos y tipos condicionales. Comprender cómo utilizar las extensiones de manera eficaz puede generar un código más sólido, reutilizable y con seguridad de escritura.

Herencia usando extensiones

Uno de los usos principales de las extensiones es la herencia, lo que le permite crear nuevas interfaces o clases que se basan en las existentes.

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

En este ejemplo, StaffUser extiende Usuario, heredando todas sus propiedades y agregando otras nuevas. Esto nos permite crear tipos más específicos basados ​​en otros más generales.

Herencia de clase

La palabra clave extends también se utiliza para la herencia de clases:

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!

Aquí, Perro extiende Animal, heredando sus propiedades y métodos, y también agregando los suyos propios.

Restricciones de tipo en genéricos

La palabra clave extends es crucial cuando se trabaja con genéricos, ya que nos permite restringir los tipos que se pueden usar con una función o clase genérica.

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. interfaz Imprimible: Aquí definimos una interfaz llamada Imprimible. Esta interfaz declara un contrato que cualquier clase que la implemente debe cumplir. El contrato especifica que cualquier clase que implemente Printable debe proporcionar un método llamado print que no acepte argumentos y devuelva void.
  2. función imprimirObjeto(obj: T): Esta es una función genérica llamada imprimirObjeto. Se necesita un único argumento llamado obj, que es de tipo T. El parámetro de tipo T está restringido a tipos que extienden (implementan) la interfaz Imprimible y se pueden usar como argumento para esta función.
  3. La clase Libro implementa Imprimible y la clase Revista implementa Imprimible: Aquí, definimos dos clases, Libro y Revista, las cuales implementan la interfaz Imprimible. Esto significa que estas clases deben proporcionar un método de impresión según lo exige el contrato de la interfaz imprimible.
  4. const miLibro = nuevo Libro(); y const myMagazine = new Magazine();: Creamos instancias de las clases Libro y Revista.
  5. imprimirObjeto(miLibro); y printObject(myRevista);: Llamamos a la función printObject con las instancias de Libro y Revista. Dado que las clases Libro y Revista implementan la interfaz Imprimible, cumplen con la restricción del parámetro de tipo Imprimible T extends. Dentro de la función, se llama al método de impresión de la clase apropiada, lo que genera el resultado esperado.
  6. // printObject(42);: Si intentamos llamar a printObject con un tipo que no implementa la interfaz Imprimible, como el número 42, TypeScript generará un error. Esto se debe a que la restricción de tipo no se cumple, ya que el número no tiene un método de impresión como lo requiere la interfaz Imprimible.

En resumen, la palabra clave extends en el contexto de la función printObject(obj: T) se usa para garantizar que el tipo T usado como argumento se adhiera al contrato definido por la interfaz Printable. Esto garantiza que solo se puedan usar tipos con un método de impresión con la función printObject, lo que impone un comportamiento y un contrato específicos para el uso de la función.

Tipos condicionales

T extends U ? X : Y
  • T es el tipo que se está comprobando
  • U es el tipo de condición con el que se verifica T.
  • X es el tipo que evalúa el tipo condicional si T extiende (es asignable a) U
  • Y es el tipo que evalúa el tipo condicional si T no extiende U
type ExtractNumber = T extends number ? T : never;

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

Aquí, el tipo ExtractNumber toma un parámetro de tipo T. El tipo condicional verifica si T extiende el tipo de número. Si es así, el tipo se resuelve en T (que es el tipo de número). Si no es así, el tipo se resuelve en nunca.

La palabra clave extiende con tipos de unión

Ahora, consideremos la expresión A | B | C extiende A. Esto puede parecer contradictorio al principio, pero en TypeScript, esta condición es en realidad falsa. He aquí por qué:

  1. En TypeScript, cuando usas extensiones con un tipo de unión en el lado izquierdo, es equivalente a preguntar: "¿Todos los tipos posibles en esta unión son asignables al tipo de la derecha?"
  2. En otras palabras, A | B | C extiende A pregunta: "¿Se puede asignar A a A, Y se puede asignar B a A, Y se puede asignar C a A?"
  3. Si bien A ciertamente se puede asignar a A, es posible que B y C no se puedan asignar a A (a menos que sean subtipos de A), por lo que el resultado general es falso.
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

En este ejemplo, IsCitrus es falso porque no todas las frutas en la unión Fruit son CitrusFruit.

Mejores prácticas y consejos

  • El uso se extiende para relaciones significativas: solo use la herencia cuando haya una relación clara "es-a" entre tipos.
  • Preferir la composición a la herencia: En muchos casos, la composición (usando interfaces e intersecciones de tipos) puede ser más flexible que la herencia de clases.
  • Tenga cuidado con las cadenas de herencia profunda: la herencia profunda puede hacer que el código sea más difícil de entender y mantener.
  • Aproveche los tipos condicionales para API flexibles: use tipos condicionales con extensiones para crear API que se adapten según los tipos de entrada.
  • El uso se extiende en genéricos para crear funciones reutilizables y con seguridad de tipos: Esto le permite escribir funciones que funcionan con una variedad de tipos manteniendo la seguridad de tipos
Declaración de liberación Este artículo se reproduce en: https://dev.to/hasanm95/mastering-typescript-understanding-the-power-of-extends-1n2o?1 Si hay alguna infracción, comuníquese con [email protected] para eliminarla.
Último tutorial Más>

Descargo de responsabilidad: Todos los recursos proporcionados provienen en parte de Internet. Si existe alguna infracción de sus derechos de autor u otros derechos e intereses, explique los motivos detallados y proporcione pruebas de los derechos de autor o derechos e intereses y luego envíelos al correo electrónico: [email protected]. Lo manejaremos por usted lo antes posible.

Copyright© 2022 湘ICP备2022001581号-3