{"id":11084,"library":"injection-js","title":"Dependency Injection for JavaScript & TypeScript","description":"injection-js is a lightweight (5.2KB minified) dependency injection library specifically designed for JavaScript and TypeScript applications outside of the Angular framework. Extracted from Angular's pre-v5 dependency injection system, it retains its feature completeness, speed, reliability, and robust testing. The library is currently at version 2.6.1 and provides a runtime reflection-based DI solution, differentiating itself from Angular's modern compile-time `StaticInjector`. It is ideal for Node.js, Vue, React, or vanilla JS/TS projects that require a sophisticated DI system without the full Angular ecosystem. Key requirements include a Reflect API polyfill (e.g., `reflect-metadata`) and specific `tsconfig.json` flags for TypeScript decorator support.","status":"active","version":"2.6.1","language":"javascript","source_language":"en","source_url":"https://github.com/mgechev/injection-js","tags":["javascript","DI","dependency","injection","dependency injection","injector","typescript"],"install":[{"cmd":"npm install injection-js","lang":"bash","label":"npm"},{"cmd":"yarn add injection-js","lang":"bash","label":"yarn"},{"cmd":"pnpm add injection-js","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"Required for the Reflect API polyfill, essential for decorator-based dependency injection in TypeScript and ES5 class syntax.","package":"reflect-metadata","optional":false},{"reason":"An alternative lightweight Reflect API polyfill, functionally equivalent to `reflect-metadata`.","package":"@abraham/reflection","optional":true},{"reason":"Can provide the Reflect API polyfill via `core-js/es7/reflect` as part of a larger polyfill bundle.","package":"core-js","optional":true}],"imports":[{"note":"The `inject` function is a modern way to declare dependencies, typically used within TypeScript classes. While `require` might work in some transpiled environments, the `import` statement is the canonical way for ESM.","wrong":"const { inject } = require('injection-js');","symbol":"inject","correct":"import { inject } from 'injection-js';"},{"note":"`ReflectiveInjector` is the core class for creating and managing dependency injectors. The CJS `require` pattern is common in older Node.js projects or for specific build setups, but ESM `import` is preferred.","wrong":"const ReflectiveInjector = require('injection-js').ReflectiveInjector;","symbol":"ReflectiveInjector","correct":"import { ReflectiveInjector } from 'injection-js';"},{"note":"`@Injectable()` is a decorator used to mark classes as providers for the injector. It's a named export, not a default export or a separate file path. Requires `experimentalDecorators` and `emitDecoratorMetadata` in `tsconfig.json`.","wrong":"import Injectable from 'injection-js/Injectable';","symbol":"Injectable","correct":"import { Injectable } from 'injection-js';"}],"quickstart":{"code":"import 'reflect-metadata'; // Must be imported once at the application entry point\nimport { inject, ReflectiveInjector, Injectable } from 'injection-js';\n\n@Injectable()\nclass HttpService {\n  public readonly baseUrl = 'https://api.example.com';\n  constructor() {\n    console.log('HttpService initialized');\n  }\n}\n\n@Injectable()\nclass LoggerService {\n  log(message: string): void {\n    console.log(`[Log] ${message}`);\n  }\n}\n\n@Injectable()\nclass DataService {\n  private http = inject(HttpService);\n  private logger = inject(LoggerService);\n\n  constructor() {\n    this.logger.log('DataService created, ready for operations.');\n  }\n\n  fetchData(): string {\n    this.logger.log(`Fetching data from: ${this.http.baseUrl}/data`);\n    return `Data from ${this.http.baseUrl} for the current user.`;\n  }\n}\n\n// Create an injector with providers\nconst appInjector = ReflectiveInjector.resolveAndCreate([\n  HttpService,\n  LoggerService,\n  DataService\n]);\n\n// Get an instance of DataService from the injector\nconst dataService = appInjector.get(DataService);\nconsole.log('Is dataService an instance of DataService?', dataService instanceof DataService);\nconsole.log('Fetched:', dataService.fetchData());\n\n// Demonstrate getting another service directly\nconst loggerService = appInjector.get(LoggerService);\nloggerService.log('Application started successfully.');\n","lang":"typescript","description":"This quickstart demonstrates setting up `injection-js` with decorators and the `inject` function, creating an injector, and resolving dependencies. It includes the necessary `reflect-metadata` import and showcases how services depend on each other."},"warnings":[{"fix":"Install `reflect-metadata` (`npm i reflect-metadata`) and add `import 'reflect-metadata';` at the very top of your application's entry file, before any decorated classes are defined. Alternatively, use `@abraham/reflection` or `core-js/es7/reflect`.","message":"Using `injection-js` with TypeScript decorators (`@Injectable`) requires a Reflect API polyfill to be present in your environment. Without it, runtime errors will occur when the injector tries to resolve types.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Add or ensure the following in your `tsconfig.json`:\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true\n  }\n}\n```","message":"When using TypeScript decorators like `@Injectable()` for dependency injection, you must enable `experimentalDecorators` and `emitDecoratorMetadata` in your `tsconfig.json` compiler options.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Understand that `injection-js` offers a runtime, reflection-based DI. If you need compile-time DI or are building an Angular application, use `@angular/core`'s built-in DI system. This library is for non-Angular applications that still desire Angular-style DI.","message":"This library is an extraction of Angular's *pre-v5* dependency injection system (`ReflectiveInjector`). It is fundamentally different from Angular v5+ `StaticInjector`, which uses compile-time DI. Do not expect compatibility with newer Angular DI patterns or the Angular compiler.","severity":"breaking","affected_versions":">=1.0.0"},{"fix":"For new projects or refactoring, prioritize using TypeScript with decorators (`@Injectable`, `constructor` type hints) or the `inject` function for dependency resolution, along with the required `tsconfig.json` settings and `reflect-metadata` polyfill.","message":"While `injection-js` supports ES6 and ES5 syntax for defining dependencies, the modern TypeScript-first approach using decorators or the `inject` function is recommended for clarity and type safety. Older patterns using `static get parameters()` or `di.Class` might be harder to maintain.","severity":"gotcha","affected_versions":">=1.0.0"}],"env_vars":null,"last_verified":"2026-04-19T00:00:00.000Z","next_check":"2026-07-18T00:00:00.000Z","problems":[{"fix":"Install `reflect-metadata` (`npm install reflect-metadata`) and add `import 'reflect-metadata';` as the very first line in your application's main entry point file. This ensures the polyfill loads before any decorated classes are defined.","cause":"The required Reflect API polyfill (`reflect-metadata` or similar) has not been imported or is not available at runtime when decorated classes are processed.","error":"TypeError: Reflect.getMetadata is not a function"},{"fix":"Open your `tsconfig.json` file and add or set `\"experimentalDecorators\": true` within the `compilerOptions` section. You will likely also need `\"emitDecoratorMetadata\": true` for `injection-js` to function correctly with decorators.","cause":"TypeScript compiler is encountering decorator syntax (`@Injectable`) but the `experimentalDecorators` flag is not enabled in `tsconfig.json`.","error":"Experimental support for decorators is a feature that is subject to change in a future release. Set the 'experimentalDecorators' option to remove this warning."}],"ecosystem":"npm"}