Documents injecute 1.x · Migrating from 0.x
Skip to content

Getting started ​

injecute is a dependency injection container for TypeScript without decorators. You register each service with a key, a factory (a function or a class) and the keys it depends on. The container resolves everything in the right order, and its type grows with every registration.

Install ​

sh
npm install injecute
sh
pnpm add injecute
sh
bun add injecute
sh
deno add npm:injecute

injecute is an ES module for Node.js ≥ 22.12, Deno, Bun and browsers, with no runtime dependencies. It also works without a build step.

Your first container ​

ts
import { DIContainer } from 'injecute';

class Database {
  constructor(readonly url: string) {}
  query(sql: string): string[] {
    return [`${this.url}: ${sql}`];
  }
}

class UserRepository {
  constructor(private readonly db: Database) {}
  findAll(): string[] {
    return this.db.query('select * from users');
  }
}

const app = new DIContainer()
  .addInstance('dbUrl', 'postgres://localhost/app')
  .addSingleton('db', Database, ['dbUrl'])
  .addSingleton('users', UserRepository, ['db']);

const users = app.get('users'); // typed as UserRepository
users.findAll();

Open in the playground

What happened:

  • addInstance('dbUrl', …) registers an existing value.
  • addSingleton('db', Database, ['dbUrl']) registers a class. The container calls new Database(dbUrl) the first time db is needed, then reuses that instance.
  • app.get('users') resolves users and everything it depends on. Its type is UserRepository, inferred from the registration.

Factory parameters and results are inferred from the registrations:

ts
import { 
DIContainer
} from 'injecute';
const
app
= new
DIContainer
()
.
addInstance
('port', 8080)
// port: number .
addSingleton
('address', (
port
) => `http://localhost:${
port
}`, ['port']);
const
address
=
app
.
get
('address'); // string

Mistakes are compile errors. A typo in a dependency key is reported on the key:

ts
app.addSingleton('server', createServer, ['adress']);
// Type '"adress"' is not assignable to type 'Dependency<…>'. Did you mean '"address"'?

Next steps ​

  • Registering services: lifetimes, optional dependencies, aliases, decoration.
  • Containers, forks and modules: forks, isolated forks for tests, modules.
  • Request context: the trace id, tenant and user of the current request in every service.
  • Scoped state: scopes for a session, a request or a transaction, and the patterns that keep every service in the root.
  • Lifecycle and dispose: releasing connections with dispose() and await using.
  • Frameworks: Express, Fastify, Hono, Next.js and GraphQL; React, Vue and Solid; coming from NestJS.
  • Roles: which part of your code gets which view of the container.

Released under the MIT License.