feat: tree-shakeable providers API updates (#22655)
Rename @Injectable({scope -> providedIn}). Instead of {providedIn: APP_ROOT_SCOPE}, accept {providedIn: 'root'}. Also, {providedIn: null} implies the injectable should not be added to any scope. PR Close #22655
This commit is contained in:

committed by
Kara Erickson

parent
21e44c6ba9
commit
db56836425
@ -55,9 +55,9 @@ export interface InjectableDecorator {
|
||||
* @stable
|
||||
*/
|
||||
(): any;
|
||||
(options?: {scope: Type<any>}&InjectableProvider): any;
|
||||
(options?: {providedIn: Type<any>| 'root' | null}&InjectableProvider): any;
|
||||
new (): Injectable;
|
||||
new (options?: {scope: Type<any>}&InjectableProvider): Injectable;
|
||||
new (options?: {providedIn: Type<any>| 'root' | null}&InjectableProvider): Injectable;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -66,7 +66,7 @@ export interface InjectableDecorator {
|
||||
* @experimental
|
||||
*/
|
||||
export interface Injectable {
|
||||
scope?: Type<any>;
|
||||
providedIn?: Type<any>|'root'|null;
|
||||
factory: () => any;
|
||||
}
|
||||
|
||||
@ -109,12 +109,19 @@ export function convertInjectableProviderToFactory(
|
||||
}
|
||||
|
||||
/**
|
||||
* Define injectable
|
||||
* Construct an `InjectableDef` which defines how a token will be constructed by the DI system, and
|
||||
* in which injectors (if any) it will be available.
|
||||
*
|
||||
* @experimental
|
||||
*/
|
||||
export function defineInjectable(opts: Injectable): Injectable {
|
||||
return opts;
|
||||
export function defineInjectable<T>(opts: {
|
||||
providedIn?: Type<any>| 'root' | null,
|
||||
factory: () => T,
|
||||
}): InjectableDef<T> {
|
||||
return {
|
||||
providedIn: opts.providedIn || null,
|
||||
factory: opts.factory,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
@ -125,19 +132,24 @@ export function defineInjectable(opts: Injectable): Injectable {
|
||||
*/
|
||||
export const Injectable: InjectableDecorator = makeDecorator(
|
||||
'Injectable', undefined, undefined, undefined,
|
||||
(injectableType: Type<any>, options: {scope: Type<any>} & InjectableProvider) => {
|
||||
if (options && options.scope) {
|
||||
(injectableType: Type<any>,
|
||||
options: {providedIn?: Type<any>| 'root' | null} & InjectableProvider) => {
|
||||
if (options && options.providedIn) {
|
||||
(injectableType as InjectableType<any>).ngInjectableDef = defineInjectable({
|
||||
scope: options.scope,
|
||||
providedIn: options.providedIn,
|
||||
factory: convertInjectableProviderToFactory(injectableType, options)
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
export interface InjectableDef<T> {
|
||||
providedIn: Type<any>|'root'|null;
|
||||
factory: () => T;
|
||||
}
|
||||
|
||||
/**
|
||||
* Type representing injectable service.
|
||||
*
|
||||
* @experimental
|
||||
*/
|
||||
export interface InjectableType<T> extends Type<T> { ngInjectableDef?: Injectable; }
|
||||
export interface InjectableType<T> extends Type<T> { ngInjectableDef: InjectableDef<T>; }
|
||||
|
@ -8,7 +8,7 @@
|
||||
|
||||
import {Type} from '../type';
|
||||
|
||||
import {Injectable, defineInjectable} from './injectable';
|
||||
import {InjectableDef, defineInjectable} from './injectable';
|
||||
|
||||
/**
|
||||
* Creates a token that can be used in a DI Provider.
|
||||
@ -36,12 +36,15 @@ export class InjectionToken<T> {
|
||||
/** @internal */
|
||||
readonly ngMetadataName = 'InjectionToken';
|
||||
|
||||
readonly ngInjectableDef: Injectable|undefined;
|
||||
readonly ngInjectableDef: InjectableDef<T>|undefined;
|
||||
|
||||
constructor(protected _desc: string, options?: {scope: Type<any>, factory: () => T}) {
|
||||
constructor(protected _desc: string, options?: {
|
||||
providedIn?: Type<any>| 'root' | null,
|
||||
factory: () => T
|
||||
}) {
|
||||
if (options !== undefined) {
|
||||
this.ngInjectableDef = defineInjectable({
|
||||
scope: options.scope,
|
||||
providedIn: options.providedIn || 'root',
|
||||
factory: options.factory,
|
||||
});
|
||||
} else {
|
||||
|
@ -10,18 +10,10 @@ import {Type} from '../type';
|
||||
import {InjectionToken} from './injection_token';
|
||||
|
||||
|
||||
// APP_ROOT_SCOPE is cast as a Type to allow for its usage as the scope parameter of @Injectable().
|
||||
|
||||
/**
|
||||
* A scope which targets the root injector.
|
||||
*
|
||||
* When specified as the `scope` parameter to `@Injectable` or `InjectionToken`, this special
|
||||
* scope indicates the provider for the service or token being configured belongs in the root
|
||||
* injector. This is loosely equivalent to the convention of having a `forRoot()` static
|
||||
* function within a module that configures the provider, and expecting users to only import that
|
||||
* module via its `forRoot()` function in the root injector.
|
||||
*
|
||||
* @experimental
|
||||
* An internal token whose presence in an injector indicates that the injector should treat itself
|
||||
* as a root scoped injector when processing requests for unknown tokens which may indicate
|
||||
* they are provided in the root scope.
|
||||
*/
|
||||
export const APP_ROOT_SCOPE: Type<any> = new InjectionToken<boolean>(
|
||||
'The presence of this token marks an injector as being the root injector.') as any;
|
||||
export const APP_ROOT = new InjectionToken<boolean>(
|
||||
'The presence of this token marks an injector as being the root injector.');
|
||||
|
Reference in New Issue
Block a user