didi: Dependency Injection Container

11.0.0 · active · verified Sun Apr 19

didi is a lightweight, battle-tested Inversion of Control (IoC) container for JavaScript and TypeScript, primarily used for dependency injection. It allows decoupling component declaration from instantiation by defining modules that declare components by name and specify how they are provided (e.g., as types, factories, or static values). The library then instantiates components on demand, transitively resolves their dependencies, and caches instances for reuse. Currently at stable version 11.0.0, didi maintains a moderate release cadence, largely driven by maintenance and dependency updates, with major version bumps often related to module system changes (e.g., ESM-only). Its key differentiators include its minimal footprint, focus on core DI patterns, and proven use in mature projects like Karma and diagram-js, making it suitable for applications requiring robust, explicit dependency management.

Common errors

Warnings

Install

Imports

Quickstart

This quickstart demonstrates defining components, configuring modules with type, factory, and value providers, and retrieving typed instances using the Injector.

import { Injector } from 'didi';

interface Engine {
  start(): void;
}

class PetrolEngine implements Engine {
  private power: number;
  constructor(power: number) {
    this.power = power;
  }
  start(): void {
    console.log(`Starting petrol engine with ${this.power}hp`);
  }
}

class ElectricEngine implements Engine {
  private voltage: number;
  constructor(voltage: number) {
    this.voltage = voltage;
  }
  start(): void {
    console.log(`Starting electric engine with ${this.voltage}V`);
  }
}

class Car {
  static $inject = ['engine', 'licensePlate'];
  private engine: Engine;
  private licensePlate: string;

  constructor(engine: Engine, licensePlate: string) {
    this.engine = engine;
    this.licensePlate = licensePlate;
  }

  start() {
    console.log(`Car with license ${this.licensePlate} is starting.`);
    this.engine.start();
  }
}

const carModule = {
  'engine': ['type', PetrolEngine],
  'power': ['value', 150],
  'licensePlate': ['value', 'XYZ-123']
};

const electricCarModule = {
  'engine': ['type', ElectricEngine],
  'voltage': ['value', 400],
  'licensePlate': ['value', 'EV-456']
};

const petrolInjector = new Injector([carModule]);
const petrolCar = petrolInjector.get<Car>('car');
petrolCar.start();

const electricInjector = new Injector([electricCarModule]);
const electricCar = electricInjector.get<Car>('car');
electricCar.start();

// Example of invoking a function with injected dependencies
petrolInjector.invoke(function(car: Car) {
  console.log('\nInvoking a function with injected car:');
  car.start();
});

view raw JSON →