In Angular, @inject
is a function used to manually inject a dependency within an injection context. It provides an alternative way to obtain instances of injectable tokens or services compared to the more common constructor injection method.
Understanding @inject
Angular's dependency injection (DI) system is fundamental to how components and services obtain the resources they need. Typically, you declare dependencies in a class's constructor, and Angular's DI system automatically provides them.
import { Component } from '@angular/core';
import { MyService } from './my.service';
@Component({ /* ... */ })
export class MyComponent {
// Constructor Injection - the standard way
constructor(private myService: MyService) {
// myService is available here
}
}
The @inject
function offers a way to access dependencies outside of the constructor parameters, specifically in locations where Angular's DI system is active.
Where Can You Use @inject?
As stated in the documentation, @inject
is only supported in an injection context. This means you can use it:
- During the construction of a class being instantiated by the DI system: This includes classes decorated with
@Injectable
,@Component
,@Directive
,@Pipe
, etc. - In the initializer for fields of such classes: You can assign the result of
inject()
directly to a class property.
Let's look at an example:
import { Component, inject } from '@angular/core';
import { MyService } from './my.service';
import { AnotherService } from './another.service';
@Component({ /* ... */ })
export class MyComponent {
// Using @inject in a field initializer
private myService = inject(MyService);
// Using @inject within the constructor (though typically constructor injection is preferred here)
private anotherService: AnotherService;
constructor() {
// inject() is supported within the constructor body
this.anotherService = inject(AnotherService);
// You can now use myService and anotherService
this.myService.doSomething();
this.anotherService.doSomethingElse();
}
}
Key Takeaway: Context Matters
It's crucial to remember that inject()
will throw an error if called outside of a valid injection context (e.g., in a plain function not involved in DI, in a constructor of a class not managed by Angular, or outside the component/service definition entirely).
Why Use @inject?
While constructor injection remains the standard and often preferred method for declaring dependencies, @inject
can be useful in certain scenarios:
- Field Initializers: It allows injecting services directly into class properties during their initialization, which can sometimes make the code slightly more concise compared to assigning them in the constructor body.
- Factory Functions: When creating dependencies using factory functions provided in
providers
,inject
can be used within the factory to obtain other services needed for the creation process. - Functional Interceptors, Guards, etc. (Angular v14+): In newer Angular versions,
@inject
is essential for accessing services within functional API definitions likeCanActivateFn
orHttpInterceptorFn
, where you don't have a traditional class constructor.
Injection Method | Common Usage | Where It Can Be Used | Advantages |
---|---|---|---|
Constructor Injection | Most components, services, directives, pipes | Constructor parameters of DI-managed classes | Clear, standard, widely understood |
@inject() Function |
Field initializers, factory functions, functional APIs | Within a valid Angular Injection Context (DI-managed class construction/fields) | Allows injection outside constructor params |
In Summary
@inject
is a function provided by Angular's core library that allows you to manually retrieve a dependency from the injector tree. Its usage is restricted to specific "injection contexts," such as the constructor or field initializers of classes managed by Angular's DI system, or within newer functional DI APIs. It serves as a powerful tool for dependency injection, especially in scenarios where constructor injection isn't feasible or ideal.