InversifyJS: Poderoso Contêiner IoC para TypeScript
InversifyJS é um contêiner IoC (Inversão de Controle) leve, mas extremamente poderoso, para aplicações TypeScript e JavaScript. Ele implementa o padrão Injeção de Dependência (DI), permitindo que desenvolvedores criem sistemas fracamente acoplados, testáveis e escaláveis. A biblioteca utiliza ativamente os recursos do TypeScript (decoradores, tipos) para garantir tipagem estrita e facilidade de desenvolvimento.
InversifyJS é ideal para aplicações server-side em Node.js, bem como para projetos client-side com frameworks como Angular, React ou Vue. Nesta visão geral, abordaremos os conceitos-chave e mostraremos como começar rapidamente.
Conceitos Principais do InversifyJS
Antes de escrever código, é importante entender as três principais entidades da biblioteca:
- Contêiner (Container) — o objeto central que gerencia todas as dependências. Você registra nele as abstrações e suas implementações.
- Identificadores de Serviço (Service Identifiers) — chaves únicas pelas quais o contêiner encontra a implementação necessária. Podem ser strings, símbolos ou classes.
- Decoradores —
@injectable()e@inject()— indicam ao TypeScript que a classe pode ser injetada e quais dependências ela precisa.
Instalação e Configuração
Para começar, instale o InversifyJS e suas dependências de tipografia:
npm install inversify reflect-metadata --savenpm install --save-dev @types/nodeEm seguida, adicione duas opções obrigatórias no tsconfig.json:
{ "compilerOptions": { "emitDecoratorMetadata": true, "experimentalDecorators": true, "types": ["reflect-metadata"] }}Depois disso, importe reflect-metadata no arquivo principal da aplicação (geralmente index.ts ou main.ts):
import "reflect-metadata";Primeiro Exemplo: Serviço Simples
Vamos criar uma interface e sua implementação. Observe o decorador @injectable():
// interfaces/IWarrior.tsexport interface IWarrior { fight(): string;}
// entities/Warrior.tsimport { injectable } from "inversify";
@injectable()export class Warrior implements IWarrior { fight(): string { return "Warrior attacks with sword!"; }}Agora registre essa relação no contêiner e obtenha uma instância:
import { Container } from "inversify";import { IWarrior } from "./interfaces/IWarrior";import { Warrior } from "./entities/Warrior";
const container = new Container();
// Registra a abstração com sua implementaçãocontainer.bind<IWarrior>("IWarrior").to(Warrior);
// Obtém uma instânciaconst warrior = container.get<IWarrior>("IWarrior");console.log(warrior.fight()); // "Warrior attacks with sword!"Injeção de Dependências via Construtor
O verdadeiro poder da DI se revela quando uma classe depende de outra. Use o decorador @inject():
// interfaces/IWeapon.tsexport interface IWeapon { use(): string;}
// entities/Sword.tsimport { injectable } from "inversify";
@injectable()export class Sword implements IWeapon { use(): string { return "Swing sword!"; }}
// 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() + " The knight fights!"; }}Registra
Também na biblioteca
Trabalhando com Apache Kafka em C++: bibliotecas e exemplos
Rate Limiting em PHP: guia completo para limitação de requisições
Envio de SMS em C# (.NET): Integração com API de Serviços SMS
Cliente OAuth para JavaScript (Node.js): visão geral e exemplos de uso
Criação de aplicações CLI em TypeScript: visão geral de frameworks e ferramentas