Dependency Injection контейнер для TypeScript: полное руководство

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Что такое Dependency Injection контейнер для TypeScript?

Dependency Injection (DI) — это паттерн проектирования, при котором объект получает свои зависимости извне, а не создает их самостоятельно. DI-контейнер — это инструмент, который управляет созданием и внедрением этих зависимостей автоматически. В TypeScript, благодаря статической типизации, DI-контейнеры особенно эффективны: они обеспечивают типобезопасность и упрощают тестирование.

Основная задача контейнера — связывать интерфейсы с их конкретными реализациями и разрешать цепочки зависимостей. Это позволяет писать слабосвязанный, модульный код, который легко поддерживать и расширять.

Зачем нужен DI-контейнер в TypeScript?

  • Уменьшение связанности кода — классы не зависят от конкретных реализаций, а только от абстракций (интерфейсов).
  • Упрощение тестирования — зависимости легко заменяются моками или стабами.
  • Управление жизненным циклом — контейнер может создавать синглтоны, транзиентные объекты или объекты с заданной областью видимости.
  • Автоматическое разрешение зависимостей — контейнер сам строит дерево зависимостей, избавляя разработчика от ручного конструирования объектов.

Популярные DI-контейнеры для TypeScript

Рассмотрим две наиболее распространенные библиотеки: InversifyJS и TSyringe. Обе поддерживают TypeScript, но имеют разные подходы.

1. InversifyJS

InversifyJS — это мощный IoC-контейнер с декораторами. Он требует явного указания зависимостей через декораторы @injectable() и @inject(). Подходит для крупных проектов с четкой архитектурой.

Установка

npm install inversify reflect-metadata --save

В файле tsconfig.json обязательно включите:

{
  "compilerOptions": {
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true
  }
}

Пример использования

import { Container, injectable, inject } from "inversify";
import "reflect-metadata";

// Определяем интерфейс и символ для привязки
interface ILogger {
  log(message: string): void;
}
const TYPES = {
  ILogger: Symbol.for("ILogger"),
  IUserService: Symbol.for("IUserService"),
};

// Реализация логгера
@injectable()
class ConsoleLogger implements ILogger {
  log(message: string): void {
    console.log(`[LOG]: ${message}`);
  }
}

// Сервис, зависящий от логгера
@injectable()
class UserService {
  constructor(@inject(TYPES.ILogger) private logger: ILogger) {}

  createUser(name: string): void {
    this.logger.log(`Пользователь ${name} создан`);
  }
}

// Настройка контейнера
const container = new Container();
container.bind<ILogger>(TYPES.ILogger).to(ConsoleLogger).inSingletonScope();
container.bind<UserService>(TYPES.IUserService).to(UserService);

// Использование
const userService = container.get<UserService>(TYPES.IUserService);
userService.createUser("Алексей");

2. TSyringe

TSyringe — легковесный DI-контейнер от Microsoft. Он использует декораторы и автоматическое разрешение через конструктор. Идеален для средних и небольших проектов.

Установка

npm install tsyringe reflect-metadata --save

Настройка tsconfig.json аналогична InversifyJS.

Пример использования

import { container, injectable, singleton } from "tsyringe";
import "reflect-metadata";

// Регистрируем класс как синглтон
@singleton()
class DatabaseConnection {
  connect(): void {
    console.log("Подключение к БД установлено");
  }
}

// Класс с автоматическим внедрением зависимости
@injectable()
class UserRepository {
  constructor(private db: DatabaseConnection) {}

  save(user: string): void {
    this.db.connect();
    console.log(`Пользователь ${user} сохранен`);
  }
}

// Регистрация в контейнере (если не используется декоратор @singleton)
// container.registerSingleton(DatabaseConnection);

// Получение экземпляра
const repo = container.resolve(UserRepository);
repo.save("Мария");

Сравнение InversifyJS и TSyringe

Характеристика InversifyJS TSyringe
Сложность Вы

Рекомендаций