askvity

What is @inject in Angular?

Published in Angular Dependency Injection 4 mins read

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 like CanActivateFn or HttpInterceptorFn, 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.

Related Articles