InversifyJS: Potente contenedor IoC para TypeScript
InversifyJS es un contenedor IoC (Inversión de Control) ligero pero extremadamente potente para aplicaciones TypeScript y JavaScript. Implementa el patrón Inyección de Dependencias (DI), permitiendo a los desarrolladores crear sistemas débilmente acoplados, testeables y escalables. La biblioteca utiliza activamente las capacidades de TypeScript (decoradores, tipos) para garantizar un tipado estricto y facilidad de desarrollo.
InversifyJS es ideal para aplicaciones de servidor en Node.js, así como para proyectos de cliente con frameworks como Angular, React o Vue. En esta revisión, analizaremos los conceptos clave y mostraremos cómo empezar rápidamente.
Conceptos principales de InversifyJS
Antes de escribir código, es importante entender las tres entidades principales de la biblioteca:
- Contenedor (Container) — el objeto central que gestiona todas las dependencias. En él se registran las abstracciones y sus implementaciones.
- Identificadores de Servicio (Service Identifiers) — claves únicas mediante las cuales el contenedor encuentra la implementación adecuada. Pueden ser cadenas, símbolos o clases.
- Decoradores —
@injectable()y@inject()— indican a TypeScript que una clase puede ser inyectada y qué dependencias necesita.
Instalación y configuración
Para empezar, instale InversifyJS y sus dependencias de tipografía:
npm install inversify reflect-metadata --savenpm install --save-dev @types/nodeLuego, agregue dos opciones obligatorias en tsconfig.json:
{ "compilerOptions": { "emitDecoratorMetadata": true, "experimentalDecorators": true, "types": ["reflect-metadata"] }}Después, importe reflect-metadata en el archivo principal de la aplicación (normalmente index.ts o main.ts):
import "reflect-metadata";Primer ejemplo: un servicio simple
Creemos una interfaz y su implementación. Observe el decorador @injectable():
// interfaces/IWarrior.tsexport interface IWarrior { fight(): string;}
// entities/Warrior.tsimport { injectable } from "inversify";
@injectable()export class Warrior implements IWarrior { fight(): string { return "¡El guerrero ataca con espada!"; }}Ahora registremos esta relación en el contenedor y obtengamos una instancia:
import { Container } from "inversify";import { IWarrior } from "./interfaces/IWarrior";import { Warrior } from "./entities/Warrior";
const container = new Container();
// Registramos la abstracción con su implementacióncontainer.bind<IWarrior>("IWarrior").to(Warrior);
// Obtenemos una instanciaconst warrior = container.get<IWarrior>("IWarrior");console.log(warrior.fight()); // "¡El guerrero ataca con espada!"Inyección de dependencias a través del constructor
El verdadero poder de la DI se revela cuando una clase depende de otra. Usamos el decorador @inject():
// interfaces/IWeapon.tsexport interface IWeapon { use(): string;}
// entities/Sword.tsimport { injectable } from "inversify";
@injectable()export class Sword implements IWeapon { use(): string { return "¡Espada en mano!"; }}
// entities/Knight.tsimport { injectable, inject } from "inversify";import { IWarrior } from "../interfaces/IWarrior";import { IWeapon } from "../interfaces/IWeapon";
@injectable()export class Knight implements IWarrior { private _weapon: IWeapon;
constructor(@inject("IWeapon") weapon: IWeapon) { this._weapon = weapon; }
fight(): string { return this._weapon.use() + " ¡El caballero lucha!"; }}Registr
También en la biblioteca
Colas de tareas para C++: implementación y uso
Envío de correo electrónico en Go (Golang): bibliotecas y ejemplos de código
RestSharp para C# (.NET): guía completa con ejemplos
Limitación de Tasa en C# (.NET): guía de la biblioteca System.Threading.RateLimiting
Procesamiento de imágenes en Go: cambio de tamaño y recorte (resize, crop)