Quick Start
Build the dependency graph through a fluent API. TypeScript matches each dependency tuple to the target constructor, so swapped and missing arguments fail at compile time. The wiring uses plain code, without @Injectable() decorators or reflect-metadata.
import { Container } from '@inferdi/inferdi'
class Logger {
log(message: string) {
console.log(`[LOG] ${message}`)
}
}
class UserRepo {
constructor(
private readonly logger: Logger,
private readonly dsn: string,
) {}
find(id: string) {
this.logger.log(`Finding ${id} in ${this.dsn}`)
}
}
const container = new Container()
.registerValue('dsn', 'postgres://localhost/app')
.registerClass('logger', Logger, [])
.registerClass('userRepo', UserRepo, ['logger', 'dsn'])
container.get('userRepo').find('42')The call to registerClass('userRepo', UserRepo, ['logger', 'dsn']) is checked positionally. If you swap the tuple to ['dsn', 'logger'], TypeScript reports the mismatch before the app runs.
Resolve Values
Use .get(key) for resolution:
const repo = container.get('userRepo')The key must be registered in the container type. Unknown static keys are compile errors. Dynamic keys should be probed with .has(key) before .get(key).
Choose Lifetimes
Registrations default to singleton. Pass the lifetime as the fourth argument for classes, or the third argument for factories.
const root = new Container()
.registerClass('logger', Logger, [])
.registerClass('request', RequestContext, [], 'scoped')
.registerClass('token', Token, [], 'transient')| Kind | Created | Cached | Disposed by container |
|---|---|---|---|
singleton | once per owning container | yes | yes |
scoped | once per scope | yes | yes |
transient | every resolve | no | no |
Singletons cannot directly depend on scoped or transient services. That rule is enforced by types and, in strict mode, by runtime guards.
