What is Inversify and why is it needed?
\n\nInversify is a powerful and lightweight IoC (Inversion of Control) container for TypeScript and JavaScript. It implements the Dependency Injection (DI) pattern, which is one of the key SOLID principles. Inversify allows you to manage dependencies between classes, making code more modular, testable, and maintainable.
\n\nWhy is it needed? In traditional programming, classes create their own dependencies (for example, via new). This leads to tight coupling of code. Inversify reverses this process: dependencies are "injected" from the outside (hence the name — Inversion of Control). The container takes over the creation and lifecycle management of objects.
Main advantages of using Inversify:
\n- \n
- Loose coupling: Classes depend on abstractions (interfaces), not on concrete implementations. \n
- Easy testing: You can easily replace real dependencies with mocks/stubs in tests. \n
- Lifecycle management: The container can create objects as singletons or as new instances each time. \n
- Readability and maintainability: All dependencies are explicitly declared and easily traceable. \n
- Scalability: Perfectly suited for large projects with many modules. \n
Installing Inversify
\n\nInversify is installed via npm. To work with TypeScript, you will also need to install reflect-metadata (a library for working with decorators) and configure tsconfig.json.
# Install Inversify and reflect-metadata\nnpm install inversify reflect-metadata --save\n\n# Install types for TypeScript (if not installed)\nnpm install @types/node --save-dev\n\n\nConfiguring tsconfig.json:
\n{\n "compilerOptions": {\n "target": "ES6",\n "module": "commonjs",\n "experimentalDecorators": true,\n "emitDecoratorMetadata": true,\n "strict": true,\n "esModuleInterop": true,\n "skipLibCheck": true,\n "forceConsistentCasingInFileNames": true,\n "outDir": "./dist",\n "rootDir": "./src",\n "types": ["reflect-metadata"]\n },\n "include": ["src/**/*"],\n "exclude": ["node_modules", "dist"]\n}\n\n\nImportant: The @injectable() and @inject() decorators only work when experimentalDecorators and emitDecoratorMetadata are enabled.
Quick Start with Code Example
\n\nLet's create a simple example: a service for sending notifications. We will have an INotificationService interface, its implementation EmailNotificationService, and a UserService class that uses this service.
// 1. Import the necessary modules\nimport "reflect-metadata";\nimport { Container, injectable, inject } from "inversify";\n\n// 2. Define the interface (abstraction)\ninterface INotificationService {\n send(message: string): void;\n}\n\n// 3. Implementation of the interface\n@injectable()\nclass EmailNotificationService implements INotificationService {\n send(message: string): void {\n console.log(`Sending email: ${message}`);\n }\n}\n\n// 4. Class that depends on INotificationService\n@injectable()\nclass UserService {\n private notificationService: INotificationService;\n\n constructor(\n @inject("INotificationService") notificationService: INotificationService\n ) {\n this.notificationService = notificationService;\n }\n\n notifyUser(userId: string): void {\n this.notificationService.send(`Notification for user ${userId}`);\n }\n}\n\n// 5. Create a container and register dependencies\nconst container = new Container();\ncontainer.bind
Also in library
Recommendations