Angular: useClass vs useExisting?
When should we use use existing provider instead of useClass ?
providers: [
{provide: Class1, useClass: Class1},
{provide: Class2, useExisting: Class2}]
: I didn't find the exact question on SO. And for better indexing decided to create this particular one here, although I found answers to this:
- Angular 2 use existing providers
- Angular 2 - useValue vs useFactory
- Angular 2 use existing providers
but I would like to have more real examples
source to share
You usually get a copy for each provider.
{provide: Class1, useClass: Class1},
equivalent to just
Class1
FROM
{provide: Class1, useClass: Class3},
you can configure that when a constructor is requested, Class1
Angular DI creates an instance Class3
and passes it to the constructor.
{provide: Class2, useExisting: Class2}
does not result in an instantiation, but you can see this, not an alias. If the constructor asks Class2
, Angular DI looks for another provider for the key Class2
and injects an instance from that provider Class2
. You can see it useExisting
as a link to another vendor or an alias.
source to share
Angular creates a factory for providers that will be used to instantiate the provider.
I usually use the following table to understand the difference between provider types.
As we can see in the figure above, all suppliers can be represented similarly useFactory
. When it's time to get an instance of the angular provider just calls the function factory
.
So for useClass
angular it resolves the dependency on an array of parameters and then calls the constructor with the parameters, and for useExisting
angular it gets the existing resolved instance and returns it.
Use cases:
1) Don't disclose full functionality
{ provide: PublicApi, useExisting: PrivateImpl } { provide: MinimalLogger, useExisting: LoggerService } { provide: PlatformRef, useExisting: PlatformRef_ } { provide: ApplicationRef, useExisting: ApplicationRef_} { provide: Sanitizer, useExisting: DomSanitizer }, { provide: Compiler, useExisting: JitCompiler }
2) Assembly tree
{ provide: Parent, useExisting: forwardRef(() => TreeViewComponent) }
3) avoid circular dependency
{ provide: BaseComponent, useExisting: forwardRef(() => MyComponent) }
4) Provide general tokens
{ provide: NG_VALIDATORS, useExisting: ForbiddenValidatorDirective, multi: true } { provide: NG_VALIDATORS, useExisting: forwardRef(() => EmailValidator), multi: true } { provide: NgControl, useExisting: forwardRef(() => NgModel) } { provide: ControlContainer, useExisting: forwardRef(() => FormGroupDirective) } { provide: NG_VALUE_ACCESSOR, multi: true, useExisting: MyDatePickerComponent }
If we replace
useExisting
with useClass
, then write the registration of a new instance of the class
source to share
useExisting - create a refrence for service example here
useClass - create a new instance of service example here
source to share