Type-Safe
Full TypeScript support with type inference and compile-time safety
Seamless dependency injection for Node.js, TypeScript and JavaScript. Clean, fully type-safe with zero external libraries and no decorators required. Inspired by .NET Core's DI system.
npm install @nodelibraries/iocimport { ServiceCollection, ServiceProvider } from '@nodelibraries/ioc';
// Define interfaces
interface ILogger {
log(message: string): void;
}
interface IUserService {
getUsers(): string[];
}
// Implementations
class Logger implements ILogger {
log(message: string) {
console.log(`[LOG] ${message}`);
}
}
class UserService implements IUserService {
constructor(private logger: ILogger) {}
getUsers(): string[] {
this.logger.log('Fetching users...');
return ['Alice', 'Bob'];
}
}
// Register services
const services = new ServiceCollection();
const ILoggerToken = Symbol('ILogger');
const IUserServiceToken = Symbol('IUserService');
// ⚠️ IMPORTANT: If a class constructor has parameters (dependencies), you MUST provide them in the dependencies array,
// and dependencies must appear in the array in the exact same order as the constructor parameters.
services.addSingleton<ILogger>(ILoggerToken, Logger); // No dependencies - constructor has no parameters
services.addScoped<IUserService>(IUserServiceToken, UserService, [ILoggerToken]); // Has dependency - MUST provide [ILoggerToken]
// Build provider
const provider = services.buildServiceProvider();
// Use services
const scope = provider.createScope();
const userService = await scope.getRequiredService<IUserService>(IUserServiceToken);
const users = userService.getUsers();@nodelibraries/ioc is a production-ready, type-safe IoC container designed for Node.js and TypeScript, inspired by .NET Core's dependency injection system. Seamlessly inject dependencies into your application with zero dependencies and no decorators required.
Learn more about our philosophy and design principles in the About guide.
No decorators, no annotations, no framework lock-in. Your code remains pure and framework-agnostic.
// Clean, simple registration
// ⚠️ IMPORTANT: If a class constructor has parameters (dependencies), you MUST provide them in the dependencies array
services.addSingleton<ILogger>(ILoggerToken, Logger); // No dependencies - constructor has no parameters
services.addScoped<IUserService>(IUserServiceToken, UserService, [ILoggerToken]); // Has dependency - MUST provide [ILoggerToken]Built from the ground up for TypeScript. Full type inference, autocomplete, and compile-time safety.
// Full type safety with autocomplete
const logger = await provider.getRequiredService<ILogger>(ILoggerToken);
logger.log('Hello'); // ✅ TypeScript knows this method existsBattle-tested features including scope validation, lifecycle hooks, and comprehensive error handling.
// Build with validation (recommended for development)
const provider = services.buildServiceProvider({
validateScopes: true, // Catch lifetime mismatches (e.g., scoped service in singleton)
validateOnBuild: true, // Validate all dependencies exist at build time
});Note: Both options default to
false. Enable them explicitly for validation. For detailed explanations, examples, and .NET Core comparison, see the Scope Validation Guide.
Circular dependencies are automatically resolved for all service lifetimes, including Transient services (which .NET Core doesn't support).
// Circular dependencies work seamlessly
class ServiceA {
constructor(private serviceB: ServiceB) {}
}
class ServiceB {
constructor(private serviceA: ServiceA) {} // ✅ Works!
}Register services using:
npm install @nodelibraries/iocNo additional configuration required! The library has zero dependencies and works out of the box.
If you find this project helpful, consider supporting it: