InversifyJS

A lightweight, decorator-driven IoC container that brings SOLID-friendly dependency injection to TypeScript and JavaScript apps.

Framework
npm
v8.2.3
286stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
84/100Excellent
Development Activity100
Maintenance100
Community52
Maturity44
Momentum40

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
81/100Excellent
Architecture88
Code Quality92
Innovation68
Learning Curve75

InversifyJS is an inversion of control (IoC) container for TypeScript and JavaScript applications. It uses a class constructor to identify a component’s dependencies and inject them automatically, replacing manual new wiring with declarative @injectable()/@inject() decorators and a fluent container.bind(...).to(...) API.

The project is maintained as a monorepo (inversify/monorepo) with the inversify package as its flagship container, built on shared internal building blocks (@inversifyjs/core, @inversifyjs/container, @inversifyjs/common) that are also reused by companion packages for HTTP framework integration, validation, logging, and OpenAPI generation. This split keeps the core container dependency-free and small while letting the ecosystem grow around it.

InversifyJS is widely used in Node.js backends, CLI tools, and any TypeScript codebase that wants class-based, constructor-injected dependencies without hand-rolling a service locator. It has shipped for over a decade, is used by teams at Microsoft, AWS Amplify, Elastic, and Slack, and continues to see active weekly releases.

What You Get

  • A Container class with a fluent bind<T>(id).to(Klass) / .toConstantValue() / .toDynamicValue() API for registering services
  • @injectable() and @inject() decorators (plus @multiInject, @named, @tagged, @optional) for declaring constructor and property dependencies
  • Binding scopes (singleton, transient, request/resolution-scoped) to control instance lifecycle
  • ContainerModule for organizing bindings into composable, reusable units
  • Hierarchical containers with parent/child lookup for scoping bindings across app boundaries
  • Activation/deactivation hooks and a plugin system (@inversifyjs/plugin) for cross-cutting concerns like disposal

Common Use Cases

  • Wiring service, repository, and controller layers in a Node.js backend without manual constructor wiring
  • Swapping real implementations for test doubles by rebinding a service identifier in unit tests
  • Building a plugin-friendly architecture where features register their own bindings via ContainerModule
  • Powering the routing/handler layer of the companion @inversifyjs/http-* framework packages (Express, Fastify, Hono, uWebSockets)
  • Scoping request-lifetime instances in web servers via resolution/request scope bindings

Under The Hood

Architecture The inversify package itself is a thin composition layer: src/index.ts re-exports the public API almost entirely from two internal workspace packages, @inversifyjs/container (the Container class, binding models, activation/deactivation actions, calculations for resolving constraints) and @inversifyjs/core (decorators, metadata reflection, planning/resolution engine, binding services), with shared primitives coming from @inversifyjs/common. Resolution follows a plan-then-execute model: decorator metadata attached via reflect-metadata is read by the planning module to build a dependency graph, which the resolution module then walks to construct instances, applying binding constraints (named/tagged/conditional) and scope rules along the way. Hierarchical containers layer child/parent lookup on top of this, and a small plugin system (onActivation/onDeactivation, @inversifyjs/plugin-dispose) hooks into the binding lifecycle for cross-cutting concerns like resource cleanup. Because the container core is isolated from any single package, the same engine is reused unmodified by the HTTP integration packages (Express, Fastify, Hono, uWebSockets) elsewhere in the monorepo.

Tech Stack The package is pure TypeScript (targeting type: module/ESM output via tsc), with reflect-metadata as its only meaningful runtime dependency for decorator metadata and no other production dependencies beyond its own workspace packages. The monorepo is managed with pnpm workspaces and Turborepo for task orchestration, uses Vitest (with a custom @inversifyjs/foundation-vitest-config preset and Stryker for mutation testing) as the test runner, ESLint/Prettier via shared @inversifyjs/foundation-* configs for linting and formatting, and Changesets for versioned releases across the many published sub-packages.

Code Quality The inversify package’s src/test/ directory contains extensive integration specs (*.int.spec.ts) covering core features (request scope, property injection, transitive bindings, named/default bindings) plus a dedicated bugs/ directory with regression tests tied to specific GitHub issue numbers, indicating a project that codifies fixes as permanent tests. Each sibling package (core, container, common) mirrors this with its own vitest.config.mjs and a parallel vitest.config.stryker.mjs for mutation testing, and CI (.github/workflows/build.yaml, collect-coverage.yaml) runs build, lint, and coverage collection across the workspace. TypeScript strictness plus ESLint/Prettier enforcement via lint-staged/Husky pre-commit hooks keeps style consistent across the many packages.

API Design The public API favors decorators and fluent chains over configuration objects: @injectable()/@inject() on classes, then container.bind<T>(id).to(Impl).inSingletonScope() for registration, which keeps most application code free of container-specific imports beyond the decorators themselves. Boilerplate to get started is minimal (two decorators and a bind/get pair), and the same container primitives extend cleanly into named/tagged bindings, container modules, and hierarchical containers without introducing a second, incompatible API surface.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search