A powerful and lightweight inversion of control container for JavaScript and Node.js apps powered by TypeScript.
npx @tessl/cli install tessl/npm-inversify@7.9.0InversifyJS is a powerful and lightweight inversion of control (IoC) container for JavaScript and Node.js applications powered by TypeScript. It enables developers to write code that adheres to SOLID principles and encourages the use of best object-oriented programming and IoC practices. The library provides dependency injection, lifecycle management, and conditional binding features with zero runtime dependencies beyond reflection metadata.
npm install inversify reflect-metadataimport { Container, injectable, inject } from "inversify";
import "reflect-metadata";For CommonJS:
const { Container, injectable, inject } = require("inversify");
require("reflect-metadata");import { Container, injectable, inject } from "inversify";
import "reflect-metadata";
// Define interfaces
interface Warrior {
fight(): string;
}
interface Weapon {
hit(): string;
}
// Implement classes with decorators
@injectable()
class Katana implements Weapon {
hit() {
return "cut!";
}
}
@injectable()
class Ninja implements Warrior {
private _weapon: Weapon;
constructor(@inject("Weapon") weapon: Weapon) {
this._weapon = weapon;
}
fight() {
return this._weapon.hit();
}
}
// Configure container and resolve dependencies
const container = new Container();
container.bind<Warrior>("Warrior").to(Ninja);
container.bind<Weapon>("Weapon").to(Katana);
const warrior = container.get<Warrior>("Warrior");
console.log(warrior.fight()); // "cut!"InversifyJS is built around several key architectural components:
Core container functionality for service registration, binding configuration, and dependency resolution. The Container class provides the primary interface for IoC operations.
class Container {
bind<T>(serviceIdentifier: ServiceIdentifier<T>): BindInFluentSyntax<T>;
rebind<T>(serviceIdentifier: ServiceIdentifier<T>): BindInFluentSyntax<T>;
unbind(serviceIdentifier: ServiceIdentifier): void;
isBound(serviceIdentifier: ServiceIdentifier): boolean;
get<T>(serviceIdentifier: ServiceIdentifier<T>): T;
getAll<T>(serviceIdentifier: ServiceIdentifier<T>): T[];
load(...modules: ContainerModule[]): void;
unload(...modules: ContainerModule[]): void;
}Core decorator functions for marking classes as injectable and specifying dependency injection points. These decorators work with TypeScript's metadata reflection system.
function injectable<T>(target: Newable<T>): void;
function inject(serviceIdentifier: ServiceIdentifier): (target: any, targetKey: string, index: number) => void;
function multiInject(serviceIdentifier: ServiceIdentifier): (target: any, targetKey: string, index: number) => void;
function named(name: string): (target: any, targetKey: string, index: number) => void;
function tagged(key: string, value: any): (target: any, targetKey: string, index: number) => void;
function optional(): (target: any, targetKey: string, index: number) => void;Fluent API for configuring service bindings including target specification, scope management, and conditional resolution. Supports various binding patterns from simple class binding to complex factory configurations.
interface BindToFluentSyntax<T> {
to(constructor: Newable<T>): BindInWhenOnFluentSyntax<T>;
toSelf(): BindInWhenOnFluentSyntax<T>;
toConstantValue(value: T): BindWhenOnFluentSyntax<T>;
toDynamicValue(func: (context: ResolutionContext) => T): BindInWhenOnFluentSyntax<T>;
toFactory<T2>(factory: Factory<T2>): BindWhenOnFluentSyntax<T>;
toProvider<T2>(provider: Provider<T2>): BindWhenOnFluentSyntax<T>;
}
interface BindInWhenOnFluentSyntax<T> {
inSingletonScope(): BindWhenOnFluentSyntax<T>;
inTransientScope(): BindWhenOnFluentSyntax<T>;
inRequestScope(): BindWhenOnFluentSyntax<T>;
}Advanced features for context-aware dependency resolution including named bindings, tagged bindings, and ancestry-based conditional resolution. Enables sophisticated dependency injection scenarios.
interface BindWhenFluentSyntax<T> {
when(constraint: (request: ResolutionContext) => boolean): BindOnFluentSyntax<T>;
whenTargetNamed(name: string): BindOnFluentSyntax<T>;
whenTargetTagged(tag: string, value: any): BindOnFluentSyntax<T>;
whenInjectedInto(parent: Newable<any>): BindOnFluentSyntax<T>;
whenParentNamed(name: string): BindOnFluentSyntax<T>;
whenParentTagged(tag: string, value: any): BindOnFluentSyntax<T>;
whenAnyAncestorIs(ancestor: Newable<any>): BindOnFluentSyntax<T>;
whenNoAncestorIs(ancestor: Newable<any>): BindOnFluentSyntax<T>;
}Lifecycle hooks and scope management for controlling service instantiation, activation, deactivation, and destruction. Supports singleton, transient, and request-scoped lifetimes.
function postConstruct(target: any, propertyKey: string): void;
function preDestroy(target: any, propertyKey: string): void;
interface BindOnFluentSyntax<T> {
onActivation(handler: (context: ResolutionContext, injectable: T) => T): BindInFluentSyntax<T>;
onDeactivation(handler: (injectable: T) => void): BindInFluentSyntax<T>;
}Container module system for organizing and packaging related service bindings. Enables modular IoC configuration and supports dynamic loading/unloading of service groups.
class ContainerModule {
constructor(
registry: (bind: BindFunction, unbind: UnbindFunction, isBound: IsBoundFunction, rebind: RebindFunction) => void
);
}
interface ContainerModuleLoadOptions {
skipDeactivation?: boolean;
}type ServiceIdentifier<T = {}> = string | symbol | Newable<T> | Abstract<T>;
type Newable<T = {}> = new (...args: any[]) => T;
interface LazyServiceIdentifier<T = {}> {
unwrap(): ServiceIdentifier<T>;
}type Factory<T> = () => T;
type Provider<T> = () => Promise<T>;
type DynamicValueBuilder<T> = (context: ResolutionContext) => T;const bindingScopeValues: {
Singleton: "Singleton";
Transient: "Transient";
Request: "Request";
};
const bindingTypeValues: {
Instance: "Instance";
Value: "Value";
Constructor: "Constructor";
Factory: "Factory";
Provider: "Provider";
Function: "Function";
DynamicValue: "DynamicValue";
};
type BindingScope = keyof typeof bindingScopeValues;interface ResolutionContext {
container: Container;
currentRequest: Request;
plan: Plan;
addPlan(plan: Plan): void;
}
interface GetOptions {
skipBaseClassChecks?: boolean;
}
interface GetAllOptions {
skipBaseClassChecks?: boolean;
}
interface OptionalGetOptions extends GetOptions {
defaultValue?: any;
}
interface GetOptionsTagConstraint {
key: string;
value: any;
}
interface MultiInjectOptions {
skipDeactivation?: boolean;
ignoreMissingBindings?: boolean;
}