Volver a la página principal
sábado 15 marzo 2025
3

Inyección de Dependencias con Inversify en Node.js con TypeScript

La inyección de dependencias (DI, por sus siglas en inglés) es un patrón de diseño ampliamente utilizado en el desarrollo de software para mejorar la modularidad y la facilidad de prueba de las aplicaciones. En el ecosistema de Node.js con TypeScript, una de las mejores opciones para implementar este patrón es InversifyJS.

📌 ¿Qué es InversifyJS?

InversifyJS es un contenedor de inyección de dependencias para JavaScript y TypeScript que sigue los principios de diseño SOLID. Algunas de sus características clave son:

✅ Soporte para decoradores de TypeScript.

✅ Compatible con arquitectura modular y escalable.

✅ Facilita la implementación del principio Inversión de Dependencias (D en SOLID).

✅ Integración sencilla con frameworks como Express.

🔧 Instalación de InversifyJS

Para comenzar, necesitamos instalar las dependencias necesarias en nuestro proyecto Node.js con TypeScript.

Ejecuta el siguiente comando:

npm install inversify reflect-metadata

También necesitamos instalar los tipos de TypeScript para Inversify:

npm install --save-dev @types/inversify

Adicionalmente, asegúrate de que tu archivo tsconfig.json tenga habilitada la opción "experimentalDecorators" y "emitDecoratorMetadata":

{
  "compilerOptions": {
    "target": "ES6",
    "module": "CommonJS",
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true
  }
}

🏗️ Creando una Aplicación con InversifyJS

Vamos a construir una estructura básica utilizando InversifyJS para gestionar dependencias en una aplicación Node.js con TypeScript.

1️⃣ Definiendo una Interfaz

Siguiendo las mejores prácticas de programación orientada a interfaces, primero creamos una interfaz para nuestro servicio:

export interface IUserService {
  getUser(id: number): string;
}

2️⃣ Creando la Implementación del Servicio

Ahora creamos una clase que implementa la interfaz IUserService:

import { injectable } from "inversify";

@injectable()
export class UserService implements IUserService {
  getUser(id: number): string {
    return `Usuario con ID: ${id}`;
  }
}

📌 Nota: La anotación @injectable() indica que esta clase puede ser gestionada por InversifyJS.

3️⃣ Configurando el Contenedor de Inversify

Inversify utiliza un contenedor de inyección de dependencias para gestionar las instancias de nuestras clases. Vamos a configurarlo:

import { Container } from "inversify";
import { IUserService } from "./interfaces/IUserService";
import { UserService } from "./services/UserService";

const container = new Container();
container.bind<IUserService>("IUserService").to(UserService);

export { container };

🔹 Aquí estamos registrando UserService como la implementación de la interfaz IUserService.

4️⃣ Inyectando Dependencias en un Controlador

Ahora creamos un controlador que utilice UserService mediante la inyección de dependencias:

import { inject, injectable } from "inversify";
import { IUserService } from "../interfaces/IUserService";

@injectable()
export class UserController {
  private userService: IUserService;

  constructor(@inject("IUserService") userService: IUserService) {
    this.userService = userService;
  }

  getUser(id: number): string {
    return this.userService.getUser(id);
  }
}

📌 Explicación:

  • @injectable(): Permite que la clase sea gestionada por Inversify.
  • @inject("IUserService"): Especifica la inyección de la dependencia IUserService.

5️⃣ Resolviendo Dependencias y Usando el Controlador

Ahora usamos el contenedor de Inversify para obtener una instancia del UserController:

import { container } from "./inversify.config";
import { UserController } from "./controllers/UserController";

const userController = container.get<UserController>(UserController);
console.log(userController.getUser(1)); // Usuario con ID: 1

🎉 ¡Listo! Ahora nuestra aplicación gestiona dependencias de forma automática y escalable.

🚀 Integrando InversifyJS con Express

Si queremos usar Inversify con Express, podemos hacerlo con el paquete inversify-express-utils.

📌 Instalación:

npm install inversify-express-utils

📌 Configuración del Servidor:

import "reflect-metadata";
import express from "express";
import { InversifyExpressServer } from "inversify-express-utils";
import { container } from "./inversify.config";

// Crear el servidor Express con Inversify
const server = new InversifyExpressServer(container);
const app = server.build();
app.listen(3000, () => console.log("Servidor corriendo en http://localhost:3000"));

📌 Creando un Controlador para Express:

import { controller, httpGet } from "inversify-express-utils";
import { inject } from "inversify";
import { IUserService } from "../interfaces/IUserService";

@controller("/users")
export class UserController {
  private userService: IUserService;

  constructor(@inject("IUserService") userService: IUserService) {
    this.userService = userService;
  }

  @httpGet("/:id")
  getUser(req: any): string {
    const id = parseInt(req.params.id);
    return this.userService.getUser(id);
  }
}

📌 Probando con Postman o el Navegador:

Si visitamos http://localhost:3000/users/1, deberíamos ver:

{
  "user": "Usuario con ID: 1"
}

📌 Conclusión

Usar InversifyJS con Node.js y TypeScript nos permite desarrollar aplicaciones modulares, escalables y fáciles de mantener. Al separar las dependencias y gestionarlas con un contenedor de inversión de control, podemos escribir código más limpio y testear nuestros componentes de manera eficiente.

Si estás construyendo una aplicación grande con TypeScript, definitivamente deberías considerar InversifyJS para gestionar la inyección de dependencias. 🚀

🔗 Recursos Adicionales

Compartir:
Creado por:
Author photo

Jorge García

Fullstack developer