Yes, deps
may be used by useFactory
or useClass
.
You can see that this is true by looking at the Angular source (5+) for packages\compiler\src\metadata_resolver.ts. If deps
is populated for either useClass
or useFactory
, then deps
will be returned in the provider metadata:
getProviderMetadata(provider: cpl.ProviderMeta): cpl.CompileProviderMetadata {
let compileDeps: cpl.CompileDiDependencyMetadata[] = undefined !;
let compileTypeMetadata: cpl.CompileTypeMetadata = null !;
let compileFactoryMetadata: cpl.CompileFactoryMetadata = null !;
let token: cpl.CompileTokenMetadata = this._getTokenMetadata(provider.token);
if (provider.useClass) {
compileTypeMetadata = this._getInjectableMetadata(provider.useClass, provider.dependencies);
compileDeps = compileTypeMetadata.diDeps; <-- ***HERE***
if (provider.token === provider.useClass) {
// use the compileTypeMetadata as it contains information about lifecycleHooks...
token = {identifier: compileTypeMetadata};
}
} else if (provider.useFactory) {
compileFactoryMetadata = this._getFactoryMetadata(provider.useFactory, provider.dependencies);
compileDeps = compileFactoryMetadata.diDeps; <-- ***HERE***
}
return {
token: token,
useClass: compileTypeMetadata,
useValue: provider.useValue,
useFactory: compileFactoryMetadata,
useExisting: provider.useExisting ? this._getTokenMetadata(provider.useExisting) : undefined,
deps: compileDeps, <-- ***HERE ***
multi: provider.multi
};
}
You can see from packages\compiler\src\view_compiler\provider_compiler.ts that deps
is used to instantiate a multi provider:
if (provider.useClass) {
const depExprs = convertDeps(providerIndex, provider.deps || provider.useClass.diDeps);
expr = ctx.importExpr(provider.useClass.reference).instantiate(depExprs); <-- ***HERE***
} else if (provider.useFactory) {
const depExprs = convertDeps(providerIndex, provider.deps || provider.useFactory.diDeps);
expr = ctx.importExpr(provider.useFactory.reference).callFn(depExprs);<-- ***HERE***
}
The same is true for single providers (https://github.com/angular/angular/blob/5.2.x/packages/compiler/src/view_compiler/provider_compiler.ts#L89).
if (providerMeta.useClass) {
providerExpr = ctx.importExpr(providerMeta.useClass.reference);
flags |= NodeFlags.TypeClassProvider;
deps = providerMeta.deps || providerMeta.useClass.diDeps; <-- ***HERE***
} else if (providerMeta.useFactory) {
providerExpr = ctx.importExpr(providerMeta.useFactory.reference);
flags |= NodeFlags.TypeFactoryProvider;
deps = providerMeta.deps || providerMeta.useFactory.diDeps; <-- ***HERE***
}
So even though it is not well documented, deps
can be used by useClass
or useFactory
.
As an aside, deps
is ignored when using useExisting
or useValue
providers (https://github.com/angular/angular/blob/5.2.x/packages/compiler/src/view_compiler/provider_compiler.ts#L108):
} else if (providerMeta.useExisting) {
providerExpr = o.NULL_EXPR;
flags |= NodeFlags.TypeUseExistingProvider;
deps = [{token: providerMeta.useExisting}];
} else {
providerExpr = convertValueToOutputAst(ctx, providerMeta.useValue);
flags |= NodeFlags.TypeValueProvider;
deps = [];
}
That being said, in the typical case, having a useClass
provider and explicitly naming dependencies in the deps
array is usually not necessary. You should let DI handle that for you implicitly.
I found some obscure use cases for it when trying to implement a static forRoot
method as referenced by these questions here and here.