Angular's dependency injection system provides a powerful and flexible way to manage services and dependencies throughout an application. It supports hierarchical injection, multiple provider types, and type-safe dependency resolution.
Primary functions for injecting dependencies and managing injection context.
/**
* Inject a dependency using its token
* @param token - The dependency token (class, InjectionToken, or string)
* @returns The dependency instance
*/
function inject<T>(token: ProviderToken<T>): T;
/**
* Inject a dependency with options
* @param token - The dependency token
* @param options - Injection options for behavior control
* @returns The dependency instance or null if optional and not found
*/
function inject<T>(token: ProviderToken<T>, options: InjectOptions): T | null;
/**
* Options for controlling injection behavior
*/
interface InjectOptions {
/** Make injection optional, return null if not found */
optional?: boolean;
/** Only look in current injector, don't traverse hierarchy */
self?: boolean;
/** Skip current injector, start from parent */
skipSelf?: boolean;
/** Specify which injector to use as host */
host?: boolean;
}
/**
* Assert that code is running in an injection context
* @param debugFn - Optional function for debug information
*/
function assertInInjectionContext(debugFn?: Function): void;
/**
* Run function in injection context with specified injector
* @param injector - The injector to use as context
* @param fn - Function to run in the injection context
* @returns The result of the function call
*/
function runInInjectionContext<T>(injector: Injector, fn: () => T): T;Core injector implementations for managing and resolving dependencies.
/**
* Abstract base class for dependency injection containers
*/
abstract class Injector {
/** Get dependency by token */
abstract get<T>(token: ProviderToken<T>): T;
/** Get dependency by token with default value */
abstract get<T>(token: ProviderToken<T>, notFoundValue: T): T;
/** Get dependency by token with null default */
abstract get<T>(token: ProviderToken<T>, notFoundValue: null): T | null;
/**
* Create a new injector with static providers
* @param providers - Array of provider configurations
* @param parent - Optional parent injector
* @returns New injector instance
*/
static create(providers: StaticProvider[], parent?: Injector): Injector;
/** The null injector which throws for all tokens */
static readonly NULL: Injector;
/** The root platform injector */
static readonly ROOT: Injector;
}
/**
* Environment injector for application-level services
*/
abstract class EnvironmentInjector extends Injector {
/**
* Destroy the injector and cleanup resources
*/
abstract destroy(): void;
/**
* Callback when injector is destroyed
*/
abstract onDestroy(callback: () => void): void;
}
/**
* Injector that can be destroyed and cleaned up
*/
interface DestroyableInjector extends Injector {
/** Destroy the injector and cleanup resources */
destroy(): void;
/** Register cleanup callback */
onDestroy(callback: () => void): void;
}Different types of providers for configuring dependency injection.
/**
* Union type for all provider configurations
*/
type Provider = ClassProvider | ValueProvider | FactoryProvider | ExistingProvider | any[];
/**
* Provider that creates instance using class constructor
*/
interface ClassProvider {
/** Token to provide */
provide: any;
/** Class to instantiate */
useClass: Type<any>;
/** Whether to provide as multi-provider array */
multi?: boolean;
}
/**
* Provider that provides a static value
*/
interface ValueProvider {
/** Token to provide */
provide: any;
/** Static value to provide */
useValue: any;
/** Whether to provide as multi-provider array */
multi?: boolean;
}
/**
* Provider that creates instance using factory function
*/
interface FactoryProvider {
/** Token to provide */
provide: any;
/** Factory function to create instance */
useFactory: Function;
/** Dependencies to inject into factory function */
deps?: any[];
/** Whether to provide as multi-provider array */
multi?: boolean;
}
/**
* Provider that aliases another token
*/
interface ExistingProvider {
/** Token to provide */
provide: any;
/** Existing token to alias */
useExisting: any;
/** Whether to provide as multi-provider array */
multi?: boolean;
}
/**
* Provider for platform-level static services
*/
interface StaticProvider {
/** Token to provide */
provide: any;
/** Value, class, factory, or existing provider */
useValue?: any;
useClass?: Type<any>;
useFactory?: Function;
useExisting?: any;
/** Dependencies for factory provider */
deps?: any[];
/** Whether to provide as multi-provider array */
multi?: boolean;
}
/**
* Providers for environment configuration
*/
type EnvironmentProviders = unknown;Type-safe tokens for non-class dependencies and configuration.
/**
* Type-safe injection token for non-class dependencies
*/
class InjectionToken<T> {
/**
* Create an injection token
* @param desc - Description for debugging
* @param options - Token configuration options
*/
constructor(desc: string, options?: {
/** Where to provide the token */
providedIn?: Type<any> | 'root' | 'platform' | 'any';
/** Factory function for creating the value */
factory?: () => T;
});
/** String representation of the token */
toString(): string;
}
/**
* Provider token type union
*/
type ProviderToken<T> = Type<T> | InjectionToken<T> | string;Utilities for resolving circular dependencies and forward references.
/**
* Create forward reference to resolve circular dependencies
* @param forwardRefFn - Function returning the referenced type
* @returns Forward reference wrapper
*/
function forwardRef(forwardRefFn: ForwardRefFn): Type<any>;
/**
* Resolve forward reference to actual value
* @param type - Type or forward reference to resolve
* @returns Resolved type
*/
function resolveForwardRef<T>(type: T): T;
/**
* Function type for forward references
*/
interface ForwardRefFn {
(): any;
}Utility functions for creating and configuring providers.
/**
* Import providers from NgModule for standalone components
* @param ngModule - Module to import providers from
* @returns Environment providers
*/
function importProvidersFrom(...ngModule: Type<any>[]): EnvironmentProviders;
/**
* Create environment-level provider configuration
* @param providers - Array of providers
* @returns Environment providers
*/
function makeEnvironmentProviders(providers: Provider[]): EnvironmentProviders;
/**
* Provide environment initialization functions
* @param initializerFn - Initialization function
* @returns Environment providers
*/
function provideEnvironmentInitializer(initializerFn: () => void): EnvironmentProviders;Standard injection tokens provided by Angular.
/** Token for the current injector instance */
const INJECTOR: InjectionToken<Injector>;
/** Token for environment initialization callbacks */
const ENVIRONMENT_INITIALIZER: InjectionToken<(() => void)[]>;
/** Token for application initialization functions */
const APP_INITIALIZER: InjectionToken<(() => Observable<unknown> | Promise<unknown> | void)[]>;
/** Token for application bootstrap listeners */
const APP_BOOTSTRAP_LISTENER: InjectionToken<((compRef: ComponentRef<any>) => void)[]>;
/** Token for unique application identifier */
const APP_ID: InjectionToken<string>;
/** Token for platform identifier */
const PLATFORM_ID: InjectionToken<Object>;
/** Token for platform initialization functions */
const PLATFORM_INITIALIZER: InjectionToken<(() => void)[]>;
/** Token for the Document object */
const DOCUMENT: InjectionToken<Document>;
/** Token for locale identifier */
const LOCALE_ID: InjectionToken<string>;
/** Token for default currency code */
const DEFAULT_CURRENCY_CODE: InjectionToken<string>;import { Injectable, inject } from '@angular/core';
import { HttpClient } from '@angular/common/http';
@Injectable({
providedIn: 'root'
})
export class UserService {
private http = inject(HttpClient);
getUsers() {
return this.http.get<User[]>('/api/users');
}
getUser(id: string) {
return this.http.get<User>(`/api/users/${id}`);
}
}import { InjectionToken, inject, Injectable } from '@angular/core';
// Define configuration interface
interface AppConfig {
apiUrl: string;
timeout: number;
retries: number;
}
// Create injection token
export const APP_CONFIG = new InjectionToken<AppConfig>('app.config', {
providedIn: 'root',
factory: () => ({
apiUrl: 'http://localhost:3000/api',
timeout: 5000,
retries: 3
})
});
// Use in service
@Injectable({
providedIn: 'root'
})
export class ApiService {
private config = inject(APP_CONFIG);
makeRequest(endpoint: string) {
console.log(`Making request to: ${this.config.apiUrl}${endpoint}`);
// Implementation...
}
}import { NgModule, InjectionToken } from '@angular/core';
// Factory provider
const RANDOM_GENERATOR = new InjectionToken<() => number>('random.generator');
function randomGeneratorFactory(): () => number {
return () => Math.random();
}
// Class provider
class LoggerService {
log(message: string) {
console.log(message);
}
}
class FileLoggerService extends LoggerService {
log(message: string) {
// Save to file instead of console
this.saveToFile(message);
}
private saveToFile(message: string) {
// File logging implementation
}
}
@NgModule({
providers: [
// Value provider
{ provide: 'API_URL', useValue: 'https://api.example.com' },
// Class provider
{ provide: LoggerService, useClass: FileLoggerService },
// Factory provider
{
provide: RANDOM_GENERATOR,
useFactory: randomGeneratorFactory
},
// Existing provider (alias)
{ provide: 'LOGGER', useExisting: LoggerService },
// Multi provider
{
provide: 'FEATURE_FLAGS',
useValue: 'feature-a',
multi: true
},
{
provide: 'FEATURE_FLAGS',
useValue: 'feature-b',
multi: true
}
]
})
export class AppModule { }import { Component, inject, Optional, Self, SkipSelf } from '@angular/core';
@Component({
selector: 'app-child',
template: `<div>Child Component</div>`,
providers: [
{ provide: 'LOCAL_SERVICE', useValue: 'child-local' }
]
})
export class ChildComponent {
// Required injection - will throw if not found
required = inject(UserService);
// Optional injection - returns null if not found
optional = inject(CacheService, { optional: true });
// Self injection - only look in current injector
local = inject('LOCAL_SERVICE', { self: true });
// Skip self - start from parent injector
parentService = inject(ParentService, { skipSelf: true });
// Host injection - look in host element's injector
hostService = inject(HostService, { host: true });
constructor() {
console.log('Optional service:', this.optional); // May be null
console.log('Local service:', this.local); // 'child-local'
}
}import {
bootstrapApplication,
importProvidersFrom,
makeEnvironmentProviders,
provideEnvironmentInitializer
} from '@angular/core';
import { RouterModule } from '@angular/router';
import { HttpClientModule } from '@angular/common/http';
// Custom environment providers
const customProviders = makeEnvironmentProviders([
{ provide: 'API_URL', useValue: 'https://api.example.com' },
{ provide: UserService, useClass: UserService }
]);
// Environment initializer
const initializeApp = provideEnvironmentInitializer(() => {
console.log('Application environment initialized');
});
// Bootstrap with providers
bootstrapApplication(AppComponent, {
providers: [
// Import from modules
importProvidersFrom(
RouterModule.forRoot(routes),
HttpClientModule
),
// Custom providers
customProviders,
// Environment initializer
initializeApp
]
});import { inject, runInInjectionContext, Injector } from '@angular/core';
// Standalone function that uses injection
function createUserManager() {
const userService = inject(UserService);
const logger = inject(LoggerService);
return {
getUser: (id: string) => {
logger.log(`Fetching user ${id}`);
return userService.getUser(id);
}
};
}
// Using function with injection context
@Component({...})
export class MyComponent {
private injector = inject(Injector);
createManager() {
return runInInjectionContext(this.injector, () => {
return createUserManager();
});
}
}