From 0f818f36d79290117c9b99f493d037f876d75c2f Mon Sep 17 00:00:00 2001 From: Pete Bacon Darwin Date: Mon, 1 Mar 2021 19:09:21 +0000 Subject: [PATCH] refactor(core): use `unknown` rather than `never` for private properties (#41040) Before `unknown` was available, the `never` type was used to discourage application developers from using "private" properties. The `unknown` type is much better suited for this. PR Close #41040 --- goldens/public-api/common/common.d.ts | 2 +- goldens/public-api/core/core.d.ts | 16 +- packages/core/src/di/injection_token.ts | 4 +- packages/core/src/di/interface/defs.ts | 30 ++-- packages/core/src/render3/definition.ts | 144 +++++++++--------- packages/core/src/render3/errors.ts | 2 +- .../core/src/render3/interfaces/definition.ts | 10 +- .../core/src/render3/util/discovery_utils.ts | 2 +- .../test/linker/ng_module_integration_spec.ts | 4 +- .../render3/instructions/lview_debug_spec.ts | 7 +- packages/core/test/render3/render_util.ts | 14 +- packages/core/test/view/ng_module_spec.ts | 20 +-- 12 files changed, 128 insertions(+), 127 deletions(-) diff --git a/goldens/public-api/common/common.d.ts b/goldens/public-api/common/common.d.ts index de956a4cec..63da20ca44 100644 --- a/goldens/public-api/common/common.d.ts +++ b/goldens/public-api/common/common.d.ts @@ -419,7 +419,7 @@ export declare abstract class ViewportScroller { abstract scrollToPosition(position: [number, number]): void; abstract setHistoryScrollRestoration(scrollRestoration: 'auto' | 'manual'): void; abstract setOffset(offset: [number, number] | (() => [number, number])): void; - static ɵprov: never; + static ɵprov: unknown; } export declare enum WeekDay { diff --git a/goldens/public-api/core/core.d.ts b/goldens/public-api/core/core.d.ts index a9f381b639..52ac3b1f5a 100644 --- a/goldens/public-api/core/core.d.ts +++ b/goldens/public-api/core/core.d.ts @@ -421,7 +421,7 @@ export declare interface InjectableDecorator { export declare type InjectableProvider = ValueSansProvider | ExistingSansProvider | StaticClassSansProvider | ConstructorSansProvider | FactorySansProvider | ClassSansProvider; export declare interface InjectableType extends Type { - ɵprov: never; + ɵprov: unknown; } export declare interface InjectDecorator { @@ -439,7 +439,7 @@ export declare enum InjectFlags { export declare class InjectionToken { protected _desc: string; - readonly ɵprov: never | undefined; + readonly ɵprov: unknown; constructor(_desc: string, options?: { providedIn?: Type | 'root' | 'platform' | 'any' | null; factory: () => T; @@ -452,7 +452,7 @@ export declare abstract class Injector { /** @deprecated */ abstract get(token: any, notFoundValue?: any): any; static NULL: Injector; static THROW_IF_NOT_FOUND: {}; - static ɵprov: never; + static ɵprov: unknown; /** @deprecated */ static create(providers: StaticProvider[], parent?: Injector): Injector; static create(options: { providers: StaticProvider[]; @@ -464,7 +464,7 @@ export declare abstract class Injector { export declare const INJECTOR: InjectionToken; export declare interface InjectorType extends Type { - ɵinj: never; + ɵinj: unknown; } export declare interface Input { @@ -510,7 +510,7 @@ export declare class IterableDiffers { /** @deprecated */ factories: IterableDifferFactory[]; constructor(factories: IterableDifferFactory[]); find(iterable: any): IterableDifferFactory; - static ɵprov: never; + static ɵprov: unknown; static create(factories: IterableDifferFactory[], parent?: IterableDiffers): IterableDiffers; static extend(factories: IterableDifferFactory[]): StaticProvider; } @@ -545,7 +545,7 @@ export declare class KeyValueDiffers { /** @deprecated */ factories: KeyValueDifferFactory[]; constructor(factories: KeyValueDifferFactory[]); find(kv: any): KeyValueDifferFactory; - static ɵprov: never; + static ɵprov: unknown; static create(factories: KeyValueDifferFactory[], parent?: KeyValueDiffers): KeyValueDiffers; static extend(factories: KeyValueDifferFactory[]): StaticProvider; } @@ -676,7 +676,7 @@ export declare function ɵɵdefineInjectable(opts: { token: unknown; providedIn?: Type | 'root' | 'platform' | 'any' | null; factory: () => T; -}): never; +}): unknown; /** @codeGenApi */ export declare function ɵɵinject(token: Type | AbstractType | InjectionToken): T; @@ -859,7 +859,7 @@ export declare function resolveForwardRef(type: T): T; export declare abstract class Sanitizer { abstract sanitize(context: SecurityContext, value: {} | string | null): string | null; - static ɵprov: never; + static ɵprov: unknown; } export declare interface SchemaMetadata { diff --git a/packages/core/src/di/injection_token.ts b/packages/core/src/di/injection_token.ts index f8b26f7eab..90386f2b1e 100644 --- a/packages/core/src/di/injection_token.ts +++ b/packages/core/src/di/injection_token.ts @@ -55,7 +55,7 @@ export class InjectionToken { /** @internal */ readonly ngMetadataName = 'InjectionToken'; - readonly ɵprov: never|undefined; + readonly ɵprov: unknown; constructor(protected _desc: string, options?: { providedIn?: Type|'root'|'platform'|'any'|null, factory: () => T @@ -82,5 +82,5 @@ export class InjectionToken { } export interface InjectableDefToken extends InjectionToken { - ɵprov: never; + ɵprov: unknown; } diff --git a/packages/core/src/di/interface/defs.ts b/packages/core/src/di/interface/defs.ts index c3ecb5ecfe..5449ed826e 100644 --- a/packages/core/src/di/interface/defs.ts +++ b/packages/core/src/di/interface/defs.ts @@ -91,7 +91,7 @@ export interface InjectableType extends Type { /** * Opaque type whose structure is highly version dependent. Do not rely on any properties. */ - ɵprov: never; + ɵprov: unknown; } /** @@ -105,7 +105,7 @@ export interface InjectorType extends Type { /** * Opaque type whose structure is highly version dependent. Do not rely on any properties. */ - ɵinj: never; + ɵinj: unknown; } /** @@ -143,13 +143,13 @@ export interface InjectorTypeWithProviders { export function ɵɵdefineInjectable(opts: { token: unknown, providedIn?: Type|'root'|'platform'|'any'|null, factory: () => T, -}): never { - return ({ - token: opts.token, - providedIn: opts.providedIn as any || null, - factory: opts.factory, - value: undefined, - } as ɵɵInjectableDef) as never; +}): unknown { + return { + token: opts.token, + providedIn: opts.providedIn as any || null, + factory: opts.factory, + value: undefined, + } as ɵɵInjectableDef; } /** @@ -180,12 +180,12 @@ export const defineInjectable = ɵɵdefineInjectable; * @codeGenApi */ export function ɵɵdefineInjector(options: {factory: () => any, providers?: any[], imports?: any[]}): - never { - return ({ - factory: options.factory, - providers: options.providers || [], - imports: options.imports || [], - } as ɵɵInjectorDef) as never; + unknown { + return { + factory: options.factory, + providers: options.providers || [], + imports: options.imports || [], + } as ɵɵInjectorDef; } /** diff --git a/packages/core/src/render3/definition.ts b/packages/core/src/render3/definition.ts index 03d665978c..9f534f651e 100644 --- a/packages/core/src/render3/definition.ts +++ b/packages/core/src/render3/definition.ts @@ -288,67 +288,65 @@ export function ɵɵdefineComponent(componentDefinition: { * The set of schemas that declare elements to be allowed in the component's template. */ schemas?: SchemaMetadata[] | null; -}): never { +}): unknown { return noSideEffects(() => { - // Initialize ngDevMode. This must be the first statement in ɵɵdefineComponent. - // See the `initNgDevMode` docstring for more information. - (typeof ngDevMode === 'undefined' || ngDevMode) && initNgDevMode(); + // Initialize ngDevMode. This must be the first statement in ɵɵdefineComponent. + // See the `initNgDevMode` docstring for more information. + (typeof ngDevMode === 'undefined' || ngDevMode) && initNgDevMode(); - const type = componentDefinition.type; - const typePrototype = type.prototype; - const declaredInputs: {[key: string]: string} = {} as any; - const def: Mutable, keyof ComponentDef> = { - type: type, - providersResolver: null, - decls: componentDefinition.decls, - vars: componentDefinition.vars, - factory: null, - template: componentDefinition.template || null!, - consts: componentDefinition.consts || null, - ngContentSelectors: componentDefinition.ngContentSelectors, - hostBindings: componentDefinition.hostBindings || null, - hostVars: componentDefinition.hostVars || 0, - hostAttrs: componentDefinition.hostAttrs || null, - contentQueries: componentDefinition.contentQueries || null, - declaredInputs: declaredInputs, - inputs: null!, // assigned in noSideEffects - outputs: null!, // assigned in noSideEffects - exportAs: componentDefinition.exportAs || null, - onPush: componentDefinition.changeDetection === ChangeDetectionStrategy.OnPush, - directiveDefs: null!, // assigned in noSideEffects - pipeDefs: null!, // assigned in noSideEffects - selectors: componentDefinition.selectors || EMPTY_ARRAY, - viewQuery: componentDefinition.viewQuery || null, - features: componentDefinition.features as DirectiveDefFeature[] || null, - data: componentDefinition.data || {}, - // TODO(misko): convert ViewEncapsulation into const enum so that it can be used - // directly in the next line. Also `None` should be 0 not 2. - encapsulation: componentDefinition.encapsulation || ViewEncapsulation.Emulated, - id: 'c', - styles: componentDefinition.styles || EMPTY_ARRAY, - _: null as never, - setInput: null, - schemas: componentDefinition.schemas || null, - tView: null, - }; - const directiveTypes = componentDefinition.directives!; - const feature = componentDefinition.features; - const pipeTypes = componentDefinition.pipes!; - def.id += _renderCompCount++; - def.inputs = invertObject(componentDefinition.inputs, declaredInputs), - def.outputs = invertObject(componentDefinition.outputs), - feature && feature.forEach((fn) => fn(def)); - def.directiveDefs = directiveTypes ? - () => (typeof directiveTypes === 'function' ? directiveTypes() : directiveTypes) - .map(extractDirectiveDef) : - null; - def.pipeDefs = pipeTypes ? - () => - (typeof pipeTypes === 'function' ? pipeTypes() : pipeTypes).map(extractPipeDef) : - null; + const type = componentDefinition.type; + const declaredInputs: {[key: string]: string} = {} as any; + const def: Mutable, keyof ComponentDef> = { + type: type, + providersResolver: null, + decls: componentDefinition.decls, + vars: componentDefinition.vars, + factory: null, + template: componentDefinition.template || null!, + consts: componentDefinition.consts || null, + ngContentSelectors: componentDefinition.ngContentSelectors, + hostBindings: componentDefinition.hostBindings || null, + hostVars: componentDefinition.hostVars || 0, + hostAttrs: componentDefinition.hostAttrs || null, + contentQueries: componentDefinition.contentQueries || null, + declaredInputs: declaredInputs, + inputs: null!, // assigned in noSideEffects + outputs: null!, // assigned in noSideEffects + exportAs: componentDefinition.exportAs || null, + onPush: componentDefinition.changeDetection === ChangeDetectionStrategy.OnPush, + directiveDefs: null!, // assigned in noSideEffects + pipeDefs: null!, // assigned in noSideEffects + selectors: componentDefinition.selectors || EMPTY_ARRAY, + viewQuery: componentDefinition.viewQuery || null, + features: componentDefinition.features as DirectiveDefFeature[] || null, + data: componentDefinition.data || {}, + // TODO(misko): convert ViewEncapsulation into const enum so that it can be used + // directly in the next line. Also `None` should be 0 not 2. + encapsulation: componentDefinition.encapsulation || ViewEncapsulation.Emulated, + id: 'c', + styles: componentDefinition.styles || EMPTY_ARRAY, + _: null, + setInput: null, + schemas: componentDefinition.schemas || null, + tView: null, + }; + const directiveTypes = componentDefinition.directives!; + const feature = componentDefinition.features; + const pipeTypes = componentDefinition.pipes!; + def.id += _renderCompCount++; + def.inputs = invertObject(componentDefinition.inputs, declaredInputs), + def.outputs = invertObject(componentDefinition.outputs), + feature && feature.forEach((fn) => fn(def)); + def.directiveDefs = directiveTypes ? + () => (typeof directiveTypes === 'function' ? directiveTypes() : directiveTypes) + .map(extractDirectiveDef) : + null; + def.pipeDefs = pipeTypes ? + () => (typeof pipeTypes === 'function' ? pipeTypes() : pipeTypes).map(extractPipeDef) : + null; - return def as never; - }) as never; + return def; + }); } /** @@ -412,7 +410,7 @@ export function ɵɵdefineNgModule(def: { /** Unique ID for the module that is used with `getModuleFactory`. */ id?: string | null; -}): never { +}): unknown { const res: NgModuleDef = { type: def.type, bootstrap: def.bootstrap || EMPTY_ARRAY, @@ -428,7 +426,7 @@ export function ɵɵdefineNgModule(def: { autoRegisterModuleById[def.id!] = def.type as unknown as NgModuleType; }); } - return res as never; + return res; } /** @@ -453,13 +451,13 @@ export function ɵɵsetNgModuleScope(type: any, scope: { * module. */ exports?: Type[] | (() => Type[]); -}): void { +}): unknown { return noSideEffects(() => { - const ngModuleDef = getNgModuleDef(type, true); - ngModuleDef.declarations = scope.declarations || EMPTY_ARRAY; - ngModuleDef.imports = scope.imports || EMPTY_ARRAY; - ngModuleDef.exports = scope.exports || EMPTY_ARRAY; - }) as never; + const ngModuleDef = getNgModuleDef(type, true); + ngModuleDef.declarations = scope.declarations || EMPTY_ARRAY; + ngModuleDef.imports = scope.imports || EMPTY_ARRAY; + ngModuleDef.exports = scope.exports || EMPTY_ARRAY; + }); } /** @@ -718,14 +716,14 @@ export function ɵɵdefinePipe(pipeDef: { /** Whether the pipe is pure. */ pure?: boolean -}): never { +}): unknown { return (>{ - type: pipeDef.type, - name: pipeDef.name, - factory: null, - pure: pipeDef.pure !== false, - onDestroy: pipeDef.type.prototype.ngOnDestroy || null - }) as never; + type: pipeDef.type, + name: pipeDef.name, + factory: null, + pure: pipeDef.pure !== false, + onDestroy: pipeDef.type.prototype.ngOnDestroy || null + }); } /** diff --git a/packages/core/src/render3/errors.ts b/packages/core/src/render3/errors.ts index 75b9392936..a8e5300492 100644 --- a/packages/core/src/render3/errors.ts +++ b/packages/core/src/render3/errors.ts @@ -22,7 +22,7 @@ export function throwMultipleComponentError(tNode: TNode): never { /** Throws an ExpressionChangedAfterChecked error if checkNoChanges mode is on. */ export function throwErrorIfNoChangesMode( - creationMode: boolean, oldValue: any, currValue: any, propName?: string): never|void { + creationMode: boolean, oldValue: any, currValue: any, propName?: string): never { const field = propName ? ` for '${propName}'` : ''; let msg = `ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value${ diff --git a/packages/core/src/render3/interfaces/definition.ts b/packages/core/src/render3/interfaces/definition.ts index aae5327804..d25d2bb514 100644 --- a/packages/core/src/render3/interfaces/definition.ts +++ b/packages/core/src/render3/interfaces/definition.ts @@ -59,7 +59,7 @@ export const enum RenderFlags { * consumable for rendering. */ export interface ComponentType extends Type { - ɵcmp: never; + ɵcmp: unknown; } /** @@ -67,8 +67,8 @@ export interface ComponentType extends Type { * consumable for rendering. */ export interface DirectiveType extends Type { - ɵdir: never; - ɵfac: () => T; + ɵdir: unknown; + ɵfac: unknown; } /** @@ -76,7 +76,7 @@ export interface DirectiveType extends Type { * consumable for rendering. */ export interface PipeType extends Type { - ɵpipe: never; + ɵpipe: unknown; } /** @@ -370,7 +370,7 @@ export interface ComponentDef extends DirectiveDef { * Used to store the result of `noSideEffects` function so that it is not removed by closure * compiler. The property should never be read. */ - readonly _?: never; + readonly _?: unknown; } /** diff --git a/packages/core/src/render3/util/discovery_utils.ts b/packages/core/src/render3/util/discovery_utils.ts index bf350235fc..1966517cd4 100644 --- a/packages/core/src/render3/util/discovery_utils.ts +++ b/packages/core/src/render3/util/discovery_utils.ts @@ -250,7 +250,7 @@ export function getLocalRefs(target: {}): {[key: string]: any} { * @globalApi ng */ export function getHostElement(componentOrDirective: {}): Element { - return getLContext(componentOrDirective)!.native as never as Element; + return getLContext(componentOrDirective)!.native as unknown as Element; } /** diff --git a/packages/core/test/linker/ng_module_integration_spec.ts b/packages/core/test/linker/ng_module_integration_spec.ts index d3dc195b99..6f3e70a3d4 100644 --- a/packages/core/test/linker/ng_module_integration_spec.ts +++ b/packages/core/test/linker/ng_module_integration_spec.ts @@ -1419,7 +1419,7 @@ function declareTests(config?: {useJit: boolean}) { } class Bar { - static ɵprov: ɵɵInjectableDef = ɵɵdefineInjectable({ + static ɵprov = ɵɵdefineInjectable({ token: Bar, factory: () => new Bar(), providedIn: SomeModule, @@ -1452,7 +1452,7 @@ function declareTests(config?: {useJit: boolean}) { } class Bar { - static ɵprov: ɵɵInjectableDef = ɵɵdefineInjectable({ + static ɵprov = ɵɵdefineInjectable({ token: Bar, factory: () => new Bar(), providedIn: SomeModule, diff --git a/packages/core/test/render3/instructions/lview_debug_spec.ts b/packages/core/test/render3/instructions/lview_debug_spec.ts index 09d7fdd90e..d1d620add6 100644 --- a/packages/core/test/render3/instructions/lview_debug_spec.ts +++ b/packages/core/test/render3/instructions/lview_debug_spec.ts @@ -7,7 +7,7 @@ */ import {Component, Injectable, ɵɵdefineComponent, ɵɵdefineDirective, ɵɵdirectiveInject, ɵɵProvidersFeature} from '@angular/core/src/core'; -import {getLContext} from '@angular/core/src/render3/context_discovery'; +import {ComponentDef, DirectiveDef} from '@angular/core/src/render3'; import {ɵɵelement, ɵɵelementEnd, ɵɵelementStart} from '@angular/core/src/render3/instructions/element'; import {TNodeDebug} from '@angular/core/src/render3/instructions/lview_debug'; import {createTNode, createTView} from '@angular/core/src/render3/instructions/shared'; @@ -227,7 +227,10 @@ describe('lView_debug', () => { expect(myCompNode.injector).toEqual({ bloom: jasmine.anything(), cumulativeBloom: jasmine.anything(), - providers: [DepA, String, MyComponent.ɵcmp, MyDirective.ɵdir], + providers: [ + DepA, String, MyComponent.ɵcmp as ComponentDef, + MyDirective.ɵdir as DirectiveDef + ], viewProviders: [DepB, Number], parentInjectorIndex: -1, }); diff --git a/packages/core/test/render3/render_util.ts b/packages/core/test/render3/render_util.ts index da369c4426..8537c7d574 100644 --- a/packages/core/test/render3/render_util.ts +++ b/packages/core/test/render3/render_util.ts @@ -294,13 +294,13 @@ export function renderTemplate( providedRendererFactory, renderer, null, null); enterView(hostLView); - const def: ComponentDef = ɵɵdefineComponent({ - type: Object, - template: templateFn, - decls: decls, - vars: vars, - consts: consts, - }); + const def = ɵɵdefineComponent({ + type: Object, + template: templateFn, + decls: decls, + vars: vars, + consts: consts, + }) as ComponentDef; def.directiveDefs = directives || null; def.pipeDefs = pipes || null; diff --git a/packages/core/test/view/ng_module_spec.ts b/packages/core/test/view/ng_module_spec.ts index 937568cfb6..29daf7da35 100644 --- a/packages/core/test/view/ng_module_spec.ts +++ b/packages/core/test/view/ng_module_spec.ts @@ -10,7 +10,7 @@ import {NgModuleRef, ɵINJECTOR_SCOPE as INJECTOR_SCOPE} from '@angular/core'; import {inject, InjectFlags} from '@angular/core/src/di'; import {Injector} from '@angular/core/src/di/injector'; import {INJECTOR} from '@angular/core/src/di/injector_token'; -import {ɵɵdefineInjectable, ɵɵInjectableDef} from '@angular/core/src/di/interface/defs'; +import {ɵɵdefineInjectable} from '@angular/core/src/di/interface/defs'; import {NgModuleDefinition, NgModuleProviderDef, NodeFlags} from '@angular/core/src/view'; import {moduleDef} from '@angular/core/src/view/ng_module'; import {createNgModuleRef} from '@angular/core/src/view/refs'; @@ -25,7 +25,7 @@ class MyChildModule {} class NotMyModule {} class Bar { - static ɵprov: ɵɵInjectableDef = ɵɵdefineInjectable({ + static ɵprov = ɵɵdefineInjectable({ token: Bar, factory: () => new Bar(), providedIn: MyModule, @@ -33,7 +33,7 @@ class Bar { } class Baz { - static ɵprov: ɵɵInjectableDef = ɵɵdefineInjectable({ + static ɵprov = ɵɵdefineInjectable({ token: Baz, factory: () => new Baz(), providedIn: NotMyModule, @@ -43,7 +43,7 @@ class Baz { class HasNormalDep { constructor(public foo: Foo) {} - static ɵprov: ɵɵInjectableDef = ɵɵdefineInjectable({ + static ɵprov = ɵɵdefineInjectable({ token: HasNormalDep, factory: () => new HasNormalDep(inject(Foo)), providedIn: MyModule, @@ -53,7 +53,7 @@ class HasNormalDep { class HasDefinedDep { constructor(public bar: Bar) {} - static ɵprov: ɵɵInjectableDef = ɵɵdefineInjectable({ + static ɵprov = ɵɵdefineInjectable({ token: HasDefinedDep, factory: () => new HasDefinedDep(inject(Bar)), providedIn: MyModule, @@ -63,7 +63,7 @@ class HasDefinedDep { class HasOptionalDep { constructor(public baz: Baz|null) {} - static ɵprov: ɵɵInjectableDef = ɵɵdefineInjectable({ + static ɵprov = ɵɵdefineInjectable({ token: HasOptionalDep, factory: () => new HasOptionalDep(inject(Baz, InjectFlags.Optional)), providedIn: MyModule, @@ -71,7 +71,7 @@ class HasOptionalDep { } class ChildDep { - static ɵprov: ɵɵInjectableDef = ɵɵdefineInjectable({ + static ɵprov = ɵɵdefineInjectable({ token: ChildDep, factory: () => new ChildDep(), providedIn: MyChildModule, @@ -80,7 +80,7 @@ class ChildDep { class FromChildWithOptionalDep { constructor(public baz: Baz|null) {} - static ɵprov: ɵɵInjectableDef = ɵɵdefineInjectable({ + static ɵprov = ɵɵdefineInjectable({ token: FromChildWithOptionalDep, factory: () => new FromChildWithOptionalDep(inject(Baz, InjectFlags.Default)), providedIn: MyChildModule, @@ -91,7 +91,7 @@ class FromChildWithSkipSelfDep { constructor( public skipSelfChildDep: ChildDep|null, public selfChildDep: ChildDep|null, public optionalSelfBar: Bar|null) {} - static ɵprov: ɵɵInjectableDef = ɵɵdefineInjectable({ + static ɵprov = ɵɵdefineInjectable({ token: FromChildWithSkipSelfDep, factory: () => new FromChildWithSkipSelfDep( inject(ChildDep, InjectFlags.SkipSelf|InjectFlags.Optional), @@ -228,7 +228,7 @@ describe('NgModuleRef_ injector', () => { Service.destroyed++; } - static ɵprov: ɵɵInjectableDef = ɵɵdefineInjectable({ + static ɵprov = ɵɵdefineInjectable({ token: Service, factory: () => new Service(), providedIn: 'root',