How to Keep Your Angular Providers from Ending Up in the Wrong Injector

Netanel Basal
Netanel Basal
Published in
2 min readMay 2, 2023

--

In Angular, registering dependency injection providers using plain functions is a common practice. However, when creating such functions, it’s important to consider their intended usage.

For instance, Angular provides several functions like provideHttpClient(), provideRouter(), and withDomHydration() that register providers under the hood. These functions are designed to be used in an environment injector, rather than in a component or a directive injector.

Suppose you’re creating a function like provideSvgIconsConfig() that registers a provider for SVG icons configuration. If you use this function in a component or a directive injector, you won't see any error. However, this can lead to unexpected behavior or errors down the line.

export function provideSvgIconsConfig(config: Partial<SVG_CONFIG>) {
return {
provide: SVG_ICONS_CONFIG,
useValue: config,
};
}
No Error

To prevent this, Angular provides the makeEnvironmentProviders function that returns an EnvironmentProviders type. This wrapper type ensures that providers intended for use only in the application/environment injector and not accidentally included in a component or directive injector.

To illustrate this, consider the updated implementation of provideSvgIconsConfig using makeEnvironmentProviders:

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

export function provideSvgIconsConfig(config: Partial<SVG_CONFIG>) {
return makeEnvironmentProviders([
{
provide: SVG_ICONS_CONFIG,
useValue: config,
},
]);
}

Now, if you try to use provideSvgIconsConfig in a component or a directive injector, you'll get a compile error. This makes it easier to catch errors and ensures that providers are used only in the intended context.

Follow me on Medium or Twitter to read more about Angular and JS!

--

--

A FrontEnd Tech Lead, blogger, and open source maintainer. The founder of ngneat, husband and father.