Skip to content

Angular Providers

A provider tells Angular's injector exactly how to create the value for a given dependency. This lesson covers the four provider forms and where you can register them.

What Is a Provider?

A provider is a recipe Angular's injector uses to produce a value for a dependency, most commonly "create a new instance of this class", but Angular also supports providing a fixed value, computing a value with a factory function, or aliasing one token to another.

The shorthand @Injectable({ providedIn: 'root' }) is actually a convenient way of registering a useClass provider for that same class at the root injector.

providers: [
  ApiService,                                   // shorthand for useClass
  { provide: ApiService, useClass: ApiService }, // equivalent, explicit form
  { provide: API_URL, useValue: 'https://api.example.com' },
]

The shorthand ApiService in a providers array is expanded by Angular into the explicit { provide: ApiService, useClass: ApiService } form.

The Four Provider Forms

{ provide: Token, useClass: SomeClass }
{ provide: Token, useValue: someValue }
{ provide: Token, useFactory: () => computeValue(), deps: [Dep1] }
{ provide: Token, useExisting: OtherToken }
  • useClass instantiates the given class whenever the token is requested.
  • useValue supplies a fixed, already-created value, no instantiation happens.
  • useFactory calls a function to compute the value, optionally injecting its own dependencies via deps.
  • useExisting aliases one token to resolve to whatever another token already provides.

Provider Forms Cheatsheet

When to reach for each provider configuration.

Form Use When
useClass You want Angular to instantiate a class as the dependency
useValue You already have the value (config object, constant, mock in tests)
useFactory The value needs computation or depends on other injected values
useExisting You want two tokens to resolve to the same underlying instance
Shorthand MyClass Simple case, equivalent to { provide: MyClass, useClass: MyClass }

useClass for Swapping Implementations

useClass is especially useful when you want a different implementation behind the same token, for example, swapping a real API service for a mock/fake in tests, or providing an environment-specific implementation.

providers: [
  { provide: LoggerService, useClass: environment.production ? ProdLoggerService : DevLoggerService },
]

useFactory With Injected Dependencies

A factory provider can itself depend on other injected values, declared in the deps array, letting you compute a value based on configuration or another service.

export const API_CLIENT = new InjectionToken<ApiClient>('API_CLIENT');

providers: [
  {
    provide: API_CLIENT,
    useFactory: (config: AppConfig) => new ApiClient(config.apiBaseUrl),
    deps: [AppConfig],
  },
]

Scoping Providers at Different Levels

Providers can be registered at the application bootstrap level, on a specific route, or on a specific component, controlling exactly how widely shared (or isolated) an instance is.

Scope Where to Register Effect
Application-wide bootstrapApplication(AppComponent, { providers: [...] }) One instance for the whole app
Route-level { path: 'orders', providers: [...] } One instance per route activation
Component-level @Component({ providers: [...] }) One instance per component instance

Common Mistakes

  • Using useValue for something that needs fresh state per instance instead of useClass or useFactory.
  • Forgetting deps on a useFactory provider, leaving the factory function unable to access its own dependencies.
  • Registering the same service both at root and again at a component level unintentionally, resulting in two separate instances.
  • Confusing useExisting (alias to another token) with useClass (create a new instance).

Key Takeaways

  • A provider tells Angular's injector how to produce a value for a given token.
  • useClass, useValue, useFactory, and useExisting cover every provider scenario.
  • Providers can be scoped at the application, route, or component level, controlling instance sharing.
  • The plain class shorthand in a providers array is sugar for an explicit useClass provider.

Pro Tip

Use environment-based useClass swapping (real service vs mock/stub) to keep local development or Storybook environments free of real network calls, without changing any component code.