Angular’s inject function retrieves the value provided for a dependency token without requiring constructor parameters. Publicly available since Angular v14, it loosens the former class-centered dependency-injection pattern: services, configuration tokens, and other DI values can be requested from functions as well as decorated classes. This makes small, composable helpers practical instead of forcing every consumer to receive a service or value as an argument. section 1.4.4 section 3.6
Use inject(Token) where Angular has an injection context. In a component or service, assigning its result to a field replaces constructor injection while avoiding an otherwise empty constructor, parameter access modifiers, and some repetitive wiring. Keep injected services private readonly where appropriate, even though field-based injection does not require constructor visibility syntax. section 3.2.1 section 3.2.4
Inject a service into a component
An employee list can declare employeeService = inject(EmployeeService) and then initialize employees$ from employeeService.getEmployees(). The component still receives the same dependency; only the declaration style changes from a constructor parameter to a field initializer. section 3.2.1
The larger payoff is functional composition. A helper can inject AuthService and expose only its authentication Observable, rather than handing every caller the full service. A footer can then call that helper for conditional rendering. This approach lets shared functions present a narrow interface while retaining access to DI-provided values. section 3.2.2
Listing 3.5 Function that returns a value from an injected service
import { inject } from '@angular/core';
import { AuthService } from '../../services/auth.service';
export function isAuth() {
const authService = inject(AuthService);
return authService.isAuth$.asObservable();
}
A small helper injects AuthService and returns a read-only authentication Observable, showing how a function can expose one service value instead of the whole service. section 3.2.2
Prefer inject when it improves the shape of the dependency boundary:
- Inject an InjectionToken directly to infer its provided type, avoiding a separately typed constructor property and the @Inject decorator. section 3.2.3
- Place dependencies on parent and child classes independently, avoiding constructor redeclaration and super calls solely for DI. section 3.2.3
- Build functional guards, resolvers, and interceptors, then migrate legacy class-based forms incrementally with Angular helper support. section 3.0 section 3.6
- Control lookup with options such as optional, self, skipSelf, and host instead of stacking constructor parameter decorators. section 3.4.1
inject does not alter Angular’s underlying DI lookup: Angular searches from the current component context through the DI tree until it finds a provider or fails. The function must therefore run in an injection context. Calling a service constructor directly with new during a unit test does not supply that context; standard TestBed-based testing does. section 3.4.1 section 3.2.4
Permission-specific functional guard
A higher-order hasPermission(permission) helper can use a closure to return a CanActivateFn for that permission. Route definitions can reuse hasPermission('CreateEmployee') or hasPermission('DeleteEmployee') instead of requiring a separate guard function for every permission. section 3.5
Adopt the function deliberately rather than mechanically. Replacing constructor injection in ordinary components may save little on its own, but function-based APIs, token injection, inheritance, and narrowly focused shared helpers benefit substantially. Legacy class-based guards, resolvers, and interceptors remain usable, allowing modernization in stages. section 3.2.2 section 3.6
