tsyringe para TypeScript: guía completa con ejemplos prácticos
En el desarrollo moderno con TypeScript, la gestión de dependencias es una tarea fundamental, especialmente al construir aplicaciones escalables y fáciles de probar. La librería tsyringe es un contenedor de inyección de dependencias (Dependency Injection, DI) ligero y potente, construido completamente sobre decoradores de TypeScript. Permite a los desarrolladores describir de forma declarativa las dependencias entre componentes, resolverlas automáticamente y gestionar el ciclo de vida de los objetos.
¿Por qué usar tsyringe? En proyectos grandes, crear instancias de clases manualmente y pasarlas a los constructores genera un código rígido, dificulta las pruebas y complica el reemplazo de implementaciones. tsyringe resuelve estos problemas proporcionando un registro centralizado (contenedor) que sabe cómo crear y proporcionar dependencias. Solo indicas qué clases o tokens deben registrarse, y el contenedor las inyecta automáticamente donde se necesitan. Esto hace que el código sea más limpio, modular y simplifica enormemente la escritura de pruebas unitarias.
La librería utiliza activamente los decoradores de TypeScript (@injectable(), @inject()), lo que hace que la sintaxis sea intuitiva para desarrolladores familiarizados con Angular o NestJS. tsyringe no requiere configuración compleja, funciona "de fábrica" con versiones modernas de TypeScript y admite varias estrategias de registro (singleton, transient, scoped). En este artículo, analizaremos en detalle todos los aspectos del trabajo con tsyringe, desde la instalación hasta casos de uso avanzados.
Instalación
Para instalar tsyringe en tu proyecto TypeScript, ejecuta el siguiente comando con npm:
npm install tsyringe reflect-metadata
Después de la instalación, asegúrate de que tu proyecto tenga configurado el soporte para decoradores. Para ello, en el archivo tsconfig.json deben estar habilitadas las siguientes opciones:
{
"compilerOptions": {
"experimentalDecorators": true,
"emitDecoratorMetadata": true
}
}
Además, en el punto de entrada de tu aplicación (por ejemplo, index.ts), debes importar reflect-metadata una sola vez para habilitar los metadatos de los decoradores:
import "reflect-metadata";
// ... resto del código
Inicio rápido: ejemplo mínimo funcional
Vamos a crear una aplicación simple que demuestre el mecanismo básico de tsyringe. Tendremos un servicio para trabajar con una base de datos, que se inyecta en un controlador.
import "reflect-metadata";
import { container, injectable, inject } from "tsyringe";
// 1. Definimos el servicio que se inyectará
@injectable()
class DatabaseService {
getData(): string {
return "Datos de la base de datos";
}
}
// 2. Definimos el controlador que depende de DatabaseService
@injectable()
class UserController {
constructor(
@inject(DatabaseService) private dbService: DatabaseService
) {}
getUserData(): string {
return this.dbService.getData();
}
}
// 3. Registramos las clases en el contenedor (en este caso no es obligatorio,
// ya que tsyringe puede resolver automáticamente las clases registradas)
container.registerSingleton(DatabaseService);
container.registerSingleton(UserController);
// 4. Usamos el contenedor para obtener una instancia del controlador
const controller = container.resolve(UserController);
console.log(controller.getUserData()); // Muestra: "Datos de la base de datos"
Este ejemplo muestra tres pasos clave: marcar la clase como @injectable(), indicar las dependencias con @inject() en el constructor y obtener una instancia mediante container.resolve(). Ten en cuenta que si la clase está registrada con el decorador
También en la biblioteca
Registro en Rust: revisión de las mejores bibliotecas y soluciones para tu proyecto
Aprendizaje automático en Swift: bibliotecas para iOS/macOS
Configuración de aplicaciones Go: librería viper
Trabajo con S3 y almacenamiento en la nube en Go: biblioteca minio-go
Registro en TypeScript: biblioteca winston