A sharp, modern, lightweight dependency injection container for TypeScript. Zero runtime dependencies, ESM + CJS support, and strong type safety.
- Zero runtime dependencies (core)
- ESM + CJS dual module format
- TypeScript 5.2+ with Stage 3 decorators
- Branded tokens for compile-time safety
- Lifecycle management: Transient, Singleton, Scoped
- Async support: factories and lifecycle hooks
- Hierarchical scopes: parent-child container relationships
- Modules: declarative provider composition
- Optional reflect-metadata integration
npm install @mrmeaow/tsinject
# or
pnpm add @mrmeaow/tsinjectFor reflect-metadata integration (optional):
npm install reflect-metadataimport { Container, createToken, injectable, inject } from '@mrmeaow/tsinject';;
// Define tokens
interface ILogger {
log(msg: string): void;
}
const ILogger = createToken<ILogger>('ILogger');
// Implement with decorator
@injectable()
class ConsoleLogger implements ILogger {
log(msg: string) {
console.log(msg);
}
}
// Register and resolve
const container = new Container();
container.registerClass(ILogger, ConsoleLogger);
const logger = container.resolve(ILogger);
logger.log('Hello tsinject');import { Container, createToken, injectable, inject } from '@mrmeaow/tsinject';;
// Transient (default) - new instance each time
container.registerClass(Token, MyService);
// Singleton - one instance per container
container.registerClass(Token, MyService, { lifecycle: Lifecycle.Singleton });
// Scoped - one instance per scope
container.registerClass(Token, MyService, { lifecycle: Lifecycle.Scoped });const root = new Container();
root.registerSingleton(Token, Service);
// Create scoped containers
const request1 = root.createScope('request1');
const request2 = root.createScope('request2');
// Each scope gets its own instance of scoped services
const svc1 = request1.resolve(Token);
const svc2 = request2.resolve(Token);import { Container, createToken, injectable, inject } from '@mrmeaow/tsinject';;
const module = defineModule({
providers: [
{ token: TokenA, provider: { type: 'class', useClass: ClassA } },
{ token: TokenB, provider: { type: 'value', useValue: 'value' } },
],
imports: [otherModule],
});
container.load(module);// Async factories
container.registerFactory(Token, async (ctx) => {
const data = await fetchData();
return new Service(data);
});
// Use resolveAsync for async factories
const instance = await container.resolveAsync(Token);@injectable() // Mark class as injectable
@injectable({ lifecycle: Lifecycle.Singleton }) // With options
@singleton() // Shorthand for singleton
@scoped() // Shorthand for scoped
@inject(Token) // Parameter injection
@optional() // Optional parameter
@lazy(Token) // Lazy property injection
@postConstruct() // Lifecycle hook
@preDestroy() // Cleanup on dispose| Method | Description |
|---|---|
createToken<T>(name) |
Create a branded token |
new Container() |
Create a container instance |
container.registerClass(token, Class, options?) |
Register a class provider |
container.registerFactory(token, factory, options?) |
Register a factory |
container.registerValue(token, value) |
Register a value |
container.registerSingleton(token, Class) |
Register as singleton |
container.resolve(token) |
Resolve synchronously |
container.resolveAsync(token) |
Resolve asynchronously |
container.tryResolve(token) |
Safe resolve (returns undefined) |
container.createScope(name) |
Create child scope |
container.has(token) |
Check if token registered |
container.dispose() |
Dispose container and calls hooks |
container.load(module) |
Load a module |
| Feature | @mrmeaow/tsinject | tsyringe | InversifyJS |
|---|---|---|---|
| Runtime deps | 0 | 1 (tslib) | 3+ (@inversifyjs/*) |
| Decorator-based | ✅ | ✅ | ✅ |
| ESM + CJS | ✅ | CJS + ESM¹ | v7: ✅ / v8: ESM only |
| reflect-metadata | optional (peer) | required | required (peer)² |
| Async resolution | ✅ | ❌ | ✅ (v7+) |
| Scopes | ✅ | ✅ | ✅ |
| Modules | ✅ | ❌ | ✅ |
Footnotes:
- tsyringe is CJS-first with ESM output, but no
"exports"field - InversifyJS lists it as peerDependency, but decorator usage requires it
MIT