Hardware FixRecommendedDevice not working? Your driver may be the problemCheck updates for common hardware issues.Fix DriversOctober DealsAmazon USOctober deal check: compare before you payAmazon US: current deals, useful picks and tech finds.Check DealsSlow PC?RecommendedPC slow today? Run a repair scan before it gets worseResolve common Windows issues and optimize system performance.Scan Now×
Skip to content
World desk6 min

Defining Dependency Providers in Angular: Tokens, Strategies and Scope

A practical guide to Angular dependency providers: choosing tokens, the four provider strategies, multi providers, and where to register a provider so the right consumers can see it.
Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

A provider tells Angular’s dependency injection system how to produce the value for a token. When a class asks for a dependency, Angular looks up the token, applies the provider’s strategy (useClass, useValue, useFactory, or useExisting) to create or reuse the value, and returns it from the first injector on the lookup path that has a matching provider. Defining a provider well means making three choices: the token that identifies the dependency, the strategy that supplies it, and the injector where it is registered.

What a provider connects

Angular’s guide to defining dependency providers describes two ways to make a service available for injection. Automatic provision places the configuration on the injectable itself, or on a token factory. Manual provision lists providers in a providers array in application configuration, in a route, or on a component or directive. The manual form is where the choices of strategy and scope are visible in your code, so the examples below use it.

As an Amazon Associate I earn from qualifying purchases.

Listing a class in providers is shorthand for an object that makes the two roles explicit:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
providers: [LocalDataService]

// equivalent to
providers: [{ provide: LocalDataService, useClass: LocalDataService }]

The provide field is the identity consumers request. Everything else in the object describes how Angular obtains the value for that identity.

Tokens: classes, interfaces and InjectionToken

A class constructor can serve as a runtime token because it exists after compilation. A TypeScript interface cannot. Interfaces are erased during compilation, so there is no runtime object Angular could use to look the dependency up, and the injection cannot be resolved. Define an InjectionToken<T> to give an interface-typed value a runtime identity:

import { InjectionToken } from '@angular/core';

export interface DataService {
  load(): Promise<string[]>;
}

export const DATA_SERVICE = new InjectionToken<DataService>('DataService');

The same approach covers configuration objects, functions, primitives, and cases where several implementations share one interface. The description string passed to the constructor is for debugging; it does not make the token unique, so the token object itself is what you import and share.

The four provider strategies

Angular’s guide documents these common strategies. Each one answers a different question about where the value comes from.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

useClass: supply an implementation

Use useClass when the token should resolve to an instance of a class. It is the standard way to substitute an implementation, such as a test double or an alternate service, behind a token:

export const appConfig: ApplicationConfig = {
  providers: [
    { provide: DATA_SERVICE, useClass: LocalDataService },
  ],
};

Consumers then receive an instance of LocalDataService when they request DATA_SERVICE.

useValue: supply a fixed value

Use useValue for configuration, URLs, primitives, and plain objects that do not need construction:

export const API_BASE_URL = new InjectionToken<string>('API_BASE_URL');

// in the providers array
{ provide: API_BASE_URL, useValue: 'https://api.example.com' }

useFactory: compute the value

Use useFactory when creation depends on other injected values or on runtime setup. Tokens listed in deps are passed to the factory as arguments, in the same order:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
{
  provide: LOGGER,
  useFactory: (config: AppConfig) => new ConsoleLogger(config.logLevel),
  deps: [APP_CONFIG],
}

useExisting: create an alias

Use useExisting when one token should point at a provider that is already registered under another token. Both tokens resolve to the same instance within that injector:

providers: [
  LocalDataService,
  { provide: DATA_SERVICE, useExisting: LocalDataService },
]

Do not replace this with a second useClass entry. A separate useClass registration creates its own instance, while useExisting preserves the one underlying provider.

Comparing the strategies

Strategy What you supply Instance behavior Typical use
useClass A class constructor Angular creates an instance for the injector that holds the provider Swapping in a real, mock or alternate implementation
useValue Any static value Consumers receive the exact value given Configuration, URLs, primitives, plain objects
useFactory A function, plus a deps list of tokens The value the function returns Creation that depends on other injected values or runtime state
useExisting Another token that is already provided Same instance as the target provider An alias that must not create a second object

Registering several contributions with multi

When several registrations should contribute to one collection, set multi: true. Consumers then receive an array under the shared token, containing one entry per registration:

export const ANALYTICS_PLUGINS =
  new InjectionToken<AnalyticsPlugin[]>('ANALYTICS_PLUGINS');

providers: [
  { provide: ANALYTICS_PLUGINS, useClass: PageViewPlugin, multi: true },
  { provide: ANALYTICS_PLUGINS, useClass: ErrorPlugin, multi: true },
]

// consumer receives an AnalyticsPlugin[] containing both instances
private plugins = inject(ANALYTICS_PLUGINS);

Where to register: injector scope

Placement decides which consumers can see a provider and whether a subtree gets its own instance. Angular documents two injector hierarchies, and the hierarchical dependency injection guide explains how they interact.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Environment injectors

Providers in application configuration, and injectables declared with providedIn (for example, providedIn: 'root'), belong to the environment hierarchy. Use this level for dependencies the whole application shares, such as an API client or a logger. In a standalone application, the array passed to bootstrapApplication in main.ts is where application-wide providers are usually declared.

Element injectors

A component’s or directive’s providers array configures its element injector. A value provided there is visible to that element and its descendants. Sibling subtrees and ancestors do not see it, and each instance of the component gets its own copy:

@Component({
  selector: 'app-cached-list',
  template: '',
  providers: [{ provide: DATA_SERVICE, useClass: CachedDataService }],
})
export class CachedListComponent {
  private data = inject(DATA_SERVICE); // CachedDataService for this subtree
}

Lookup order

Angular searches from the point where the request is made, moving up the element injector hierarchy first. If the token is not found there, it continues through the environment injector hierarchy. The first matching provider wins, so a component-level provider for a token shadows an application-level provider for the same token within its subtree.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Calling inject()

The inject() function reads a token from the active injector. It only works inside an injection context: during construction of a class that Angular instantiates through DI, in the field initializers of such a class, and in provider factory functions. Elsewhere it throws, so keep it out of ordinary methods:

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
export class ItemsComponent {
  private data = inject(DATA_SERVICE); // field initializer: valid

  reload() {
    const data = inject(DATA_SERVICE); // invalid: a method is not an injection context
  }
}

Choosing a provider

Work through these questions in order:

  1. Is the dependency a concrete class you want to use as its own identity? List the class directly.
  2. Is the requested type an interface, a primitive, a configuration object, or a function? Create an InjectionToken for it.
  3. Is the value fixed? Use useValue.
  4. Does creating the value require other injected values? Use useFactory with a deps list.
  5. Must two tokens share one instance? Use useExisting. If each token should get its own instance, use useClass for each.
  6. Do several registrations contribute to one collection? Add multi: true.
  7. Who needs the value? Application-wide dependencies go in environment-level configuration or providedIn: 'root'. Dependencies that should be isolated to a component subtree go in that component’s or directive’s providers.

Common mistakes

  • Injecting an interface type. Interfaces have no runtime identity. Create an InjectionToken and provide under it.
  • Expecting useExisting to create a new instance. It aliases an existing provider; use useClass when you want a separate object.
  • Providing a service on one component and expecting another part of the app to see it. The provider is only visible to that element and its descendants. Move it to the environment level if it should be shared.
  • Calling inject() in a method. Read the value in a constructor or field initializer and store it.
  • Missing registration. If no injector on the lookup path has a provider for the token, Angular fails to resolve it. Register the token at a level that is an ancestor of the consumer.

Versions and scope

The examples follow Angular’s current guides, which describe the standalone application style. Angular APIs and recommended patterns change between releases, so confirm the signatures and configuration locations against the documentation for the version your project uses. The Dependency Injection overview defines a dependency as “any object, value, function, or service that a class requires but does not create itself,” and that definition is the frame for every choice above.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Leave a Reply

Your email address will not be published. Required fields are marked *

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

More from the Wire

  1. World desk4 min
    How to Spot an AI Voice Scam Before Sending MoneyDon’t rely on how a caller sounds. Pause, call back through a known number, and verify the emergency with another trusted person before sending money.
  2. Mountain View desk4 min
    Google’s SynthID Detector: How to Check AI-Generated Images, Video and AudioGoogle’s SynthID Detector looks for an embedded watermark in supported images, video and audio. Here is what its results do—and do not—show.
  3. Redmond desk20 min
    How to create a link to File or Folder in Windows 11Windows 11 gives you several ways to point to a file or folder without moving or duplicating it. You can create a desktop shortcut,…
Recommended PC Tool
Recommended PC Tool
Windows Errors? Fix Them Before They SpreadFree repair scan
Outdated Drivers Are Slowing You DownFree scan - exact matches

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.