Aumento de módulos en TypeScript

Antes de adentrarnos en la ampliación de módulos, veamos algunos principios de fusión de TypeScript que resultarán útiles a medida que avancemos.
En esta publicación, hablamos sobre la fusión de interfaces con interfaces. Además, también podemos fusionar interfaces con clases. Veamos un ejemplo.
class Food { cheese: string;}interface Food { bacon: string;}const food = new Food();food.bacon = "nice bacon";food.cheese = "sweet cheese";console.log(food); // {bacon: "nice bacon", cheese: "sweet cheese"}
En nuestro ejemplo anterior, podemos ver que la food
variable contiene tanto bacon
y cheese
como aunque solo cheese
se declaró en la Food
clase. Esto se debe a que la interfaz se fusionó con la clase.
Pero ¿qué pasa si nuestra interfaz contiene un método, por ejemplo,bake
class Food { cheese: string;}interface Food { bacon: string; bake(item: string);}const food = new Food();food.bake("cake"); // Error: food.bake is not a function
Aunque el bake
método se mostrará en la food
variable con la ayuda de intelliSense, debido a que la clase Food
y la interfaz Food
se fusionarán, llamar al bake
método generará un error porque las interfaces solo contienen declaraciones, pero no implementaciones. Para resolver esto, podemos agregar la implementación de bake
al Food
prototipo.
Food.prototype.bake = (item) = console.log(item);
Ahora llamar al bake
método funcionará.
food.bake("cake"); // cake
Ingresar al módulo de ampliación
La ampliación de módulos nos ayuda a ampliar las funcionalidades de bibliotecas de terceros a las que quizás no tengamos acceso o a clases en otros archivos.
Digamos que tenemos una Pet
clase con una name
propiedad y feed
un método.
mascota.ts
export class Pet { name: string; feed(feedType: string) { console.log(feedType); }}
Luego decidimos importar esta clase a nuestro index.ts
archivo, pero en lugar de usar solo los métodos y propiedades de la Pet
clase, queremos agregar más funcionalidades. Podemos hacerlo usando module augmentation .
Primero, importamos nuestra Pet
clase a nuestro index.ts
archivo.
índice.ts
import { Pet } from "./pet";
./pet
es un módulo. Para poder extenderlo, debemos declarar un módulo con el mismo nombre y en ese módulo, declararemos una interfaz con el mismo nombre que la clase que estamos intentando extender. En la interfaz, incluiremos las propiedades y métodos que queremos agregar a la clase extendida.
índice.ts
declare module "./pet" { interface Pet { age: number; walk(location: string); }}
TypeScript fusionará tanto la Pet
clase como la Pet
interfaz porque se pueden encontrar en el mismo ./pet
módulo.
Pero eso no es todo. Recuerda que expliqué que las interfaces no contienen la implementación de los métodos sino solo sus declaraciones. Por ese motivo, agregaremos la implementación del walk
método al prototype
of Pet
.
Pet.prototype.walk = (location:string) = `Likes to walk in the ${location}`
Ahora podemos llamar a los métodos y propiedades que se encuentran en la Pet
clase y a la interfaz recién declarada Pet
.
índice.ts
const pet = new Pet();pet.name = "Looty";pet.age = 3;pet.feed("bacon"); // baconconsole.log(pet.name = "Looty"); // Lootyconsole.log(pet.age = 3); // 3console.log(pet.walk("park")); // Likes to walk in the park
Ahora quizás te preguntes, en lugar de declarar una interfaz y luego agregar la implementación del walk
método al Pet
prototipo, ¿por qué no declaramos simplemente una clase con el mismo nombre para que cuando se inicialice la clase, tengamos métodos de ambas clases?
La respuesta es que TypeScript no permite fusionar clases, por lo que no podemos crear dos o más clases con el mismo nombre. Si quieres fusionar clases, existe una solución alternativa que utiliza los mixins de TypeScript que se comentan en esta publicación o puedes usar una biblioteca que creé solo para eso.
Eso es todo. Espero que te haya resultado útil.
Deja una respuesta