From 2200884e5570a9341e989a6e6f798d9cf032529a Mon Sep 17 00:00:00 2001 From: Paul Gschwendtner Date: Fri, 14 Jun 2019 09:27:41 +0200 Subject: [PATCH] refactor(core): ensure compatibility with typescript strict flag (#30993) As part of FW-1265, the `@angular/core` package is made compatible with the TypeScript `--strict` flag. This already unveiled a few bugs, so the strictness flag seems to help with increasing the overall code health. Read more about the strict flag [here](https://www.typescriptlang.org/docs/handbook/compiler-options.html) PR Close #30993 --- packages/BUILD.bazel | 6 +++ packages/core/src/debug/debug_node.ts | 37 +++++++++++++------ packages/core/src/di/injectable.ts | 6 +-- .../core/src/di/injector_compatibility.ts | 4 +- packages/core/src/di/reflective_provider.ts | 5 ++- .../linker/ng_module_factory_registration.ts | 2 +- packages/core/src/metadata/ng_module.ts | 6 +-- packages/core/src/render3/definition.ts | 7 ++-- packages/core/src/render3/di.ts | 2 +- packages/core/src/render3/di_setup.ts | 9 +++-- .../core/src/render3/instructions/shared.ts | 5 +-- .../core/src/render3/interfaces/injector.ts | 8 ++-- packages/core/src/render3/pipe.ts | 2 +- .../styling/host_instructions_queue.ts | 2 +- .../src/render3/styling_next/styling_debug.ts | 7 ++-- .../core/src/render3/styling_next/util.ts | 4 +- packages/core/src/util/decorators.ts | 12 +++--- packages/core/src/zone/ng_zone.ts | 2 +- packages/core/test/render3/render_util.ts | 2 +- .../styling/class_and_style_bindings_spec.ts | 4 +- packages/core/testing/src/async_fallback.ts | 4 +- .../core/testing/src/fake_async_fallback.ts | 2 +- .../core/testing/src/r3_test_bed_compiler.ts | 29 ++++++++------- packages/core/testing/src/test_bed.ts | 8 ++-- packages/core/testing/src/testing_internal.ts | 15 +++++--- packages/tsconfig-build-no-strict.json | 10 +++++ packages/tsconfig-build.json | 1 + packages/tsconfig-test.json | 5 ++- tools/public_api_guard/core/core.d.ts | 2 +- 29 files changed, 122 insertions(+), 86 deletions(-) create mode 100644 packages/tsconfig-build-no-strict.json diff --git a/packages/BUILD.bazel b/packages/BUILD.bazel index b3202fba0d4ce..d8c022c6f96e3 100644 --- a/packages/BUILD.bazel +++ b/packages/BUILD.bazel @@ -23,6 +23,12 @@ ts_config( deps = [":tsconfig-build.json"], ) +ts_config( + name = "tsconfig-build-no-strict", + src = "tsconfig-build-no-strict.json", + deps = [":tsconfig-build.json"], +) + exports_files([ "license-banner.txt", "README.md", diff --git a/packages/core/src/debug/debug_node.ts b/packages/core/src/debug/debug_node.ts index adeb75ee1590e..81533f2a226f1 100644 --- a/packages/core/src/debug/debug_node.ts +++ b/packages/core/src/debug/debug_node.ts @@ -440,9 +440,15 @@ class DebugElement__POST_R3__ extends DebugNode__POST_R3__ implements DebugEleme * @param matches the list of positive matches * @param elementsOnly whether only elements should be searched */ +function _queryAllR3( + parentElement: DebugElement, predicate: Predicate, matches: DebugElement[], + elementsOnly: true): void; function _queryAllR3( parentElement: DebugElement, predicate: Predicate, matches: DebugNode[], - elementsOnly: boolean) { + elementsOnly: false): void; +function _queryAllR3( + parentElement: DebugElement, predicate: Predicate| Predicate, + matches: DebugElement[] | DebugNode[], elementsOnly: boolean) { const context = loadLContext(parentElement.nativeNode) !; const parentTNode = context.lView[TVIEW].data[context.nodeIndex] as TNode; _queryNodeChildrenR3( @@ -457,11 +463,11 @@ function _queryAllR3( * @param predicate the predicate to match * @param matches the list of positive matches * @param elementsOnly whether only elements should be searched - * @param rootNativeNode the root native node on which prediccate shouold not be matched + * @param rootNativeNode the root native node on which predicate should not be matched */ function _queryNodeChildrenR3( - tNode: TNode, lView: LView, predicate: Predicate, matches: DebugNode[], - elementsOnly: boolean, rootNativeNode: any) { + tNode: TNode, lView: LView, predicate: Predicate| Predicate, + matches: DebugElement[] | DebugNode[], elementsOnly: boolean, rootNativeNode: any) { const nativeNode = getNativeByTNode(tNode, lView); // For each type of TNode, specific logic is executed. if (tNode.type === TNodeType.Element || tNode.type === TNodeType.ElementContainer) { @@ -535,11 +541,11 @@ function _queryNodeChildrenR3( * @param predicate the predicate to match * @param matches the list of positive matches * @param elementsOnly whether only elements should be searched - * @param rootNativeNode the root native node on which prediccate shouold not be matched + * @param rootNativeNode the root native node on which predicate should not be matched */ function _queryNodeChildrenInContainerR3( - lContainer: LContainer, predicate: Predicate, matches: DebugNode[], - elementsOnly: boolean, rootNativeNode: any) { + lContainer: LContainer, predicate: Predicate| Predicate, + matches: DebugElement[] | DebugNode[], elementsOnly: boolean, rootNativeNode: any) { for (let i = CONTAINER_HEADER_OFFSET; i < lContainer.length; i++) { const childView = lContainer[i]; _queryNodeChildrenR3( @@ -554,16 +560,23 @@ function _queryNodeChildrenInContainerR3( * @param predicate the predicate to match * @param matches the list of positive matches * @param elementsOnly whether only elements should be searched - * @param rootNativeNode the root native node on which prediccate shouold not be matched + * @param rootNativeNode the root native node on which predicate should not be matched */ function _addQueryMatchR3( - nativeNode: any, predicate: Predicate, matches: DebugNode[], elementsOnly: boolean, - rootNativeNode: any) { + nativeNode: any, predicate: Predicate| Predicate, + matches: DebugElement[] | DebugNode[], elementsOnly: boolean, rootNativeNode: any) { if (rootNativeNode !== nativeNode) { const debugNode = getDebugNode(nativeNode); - if (debugNode && (elementsOnly ? debugNode instanceof DebugElement__POST_R3__ : true) && - predicate(debugNode)) { + if (!debugNode) { + return; + } + // Type of the "predicate and "matches" array are set based on the value of + // the "elementsOnly" parameter. TypeScript is not able to properly infer these + // types with generics, so we manually cast the parameters accordingly. + if (elementsOnly && debugNode instanceof DebugElement__POST_R3__ && predicate(debugNode)) { matches.push(debugNode); + } else if (!elementsOnly && (predicate as Predicate)(debugNode)) { + (matches as DebugNode[]).push(debugNode); } } } diff --git a/packages/core/src/di/injectable.ts b/packages/core/src/di/injectable.ts index 107e2b5bbf369..d6c5ea3de5770 100644 --- a/packages/core/src/di/injectable.ts +++ b/packages/core/src/di/injectable.ts @@ -92,10 +92,10 @@ export interface InjectableType extends Type { ngInjectableDef: ɵɵInject * Supports @Injectable() in JIT mode for Render2. */ function render2CompileInjectable( - injectableType: InjectableType, - options: {providedIn?: Type| 'root' | null} & InjectableProvider): void { + injectableType: Type, + options?: {providedIn?: Type| 'root' | null} & InjectableProvider): void { if (options && options.providedIn !== undefined && !getInjectableDef(injectableType)) { - injectableType.ngInjectableDef = ɵɵdefineInjectable({ + (injectableType as InjectableType).ngInjectableDef = ɵɵdefineInjectable({ token: injectableType, providedIn: options.providedIn, factory: convertInjectableProviderToFactory(injectableType, options), diff --git a/packages/core/src/di/injector_compatibility.ts b/packages/core/src/di/injector_compatibility.ts index 83cc2638abc86..dd78ea322ede8 100644 --- a/packages/core/src/di/injector_compatibility.ts +++ b/packages/core/src/di/injector_compatibility.ts @@ -68,8 +68,8 @@ export function setCurrentInjector(injector: Injector | null | undefined): Injec * 1. `Injector` should not depend on ivy logic. * 2. To maintain tree shake-ability we don't want to bring in unnecessary code. */ -let _injectImplementation: ((token: Type| InjectionToken, flags: InjectFlags) => T | null)| - undefined; +let _injectImplementation: + ((token: Type| InjectionToken, flags?: InjectFlags) => T | null)|undefined; /** * Sets the current inject implementation. diff --git a/packages/core/src/di/reflective_provider.ts b/packages/core/src/di/reflective_provider.ts index f9a8c26e7b13d..96286d9594c39 100644 --- a/packages/core/src/di/reflective_provider.ts +++ b/packages/core/src/di/reflective_provider.ts @@ -180,10 +180,11 @@ export function mergeResolvedReflectiveProviders( return normalizedProvidersMap; } -function _normalizeProviders(providers: Provider[], res: Provider[]): Provider[] { +function _normalizeProviders( + providers: Provider[], res: NormalizedProvider[]): NormalizedProvider[] { providers.forEach(b => { if (b instanceof Type) { - res.push({provide: b, useClass: b}); + res.push({ provide: b, useClass: b } as NormalizedProvider); } else if (b && typeof b == 'object' && (b as any).provide !== undefined) { res.push(b as NormalizedProvider); diff --git a/packages/core/src/linker/ng_module_factory_registration.ts b/packages/core/src/linker/ng_module_factory_registration.ts index 60ed6d603dc68..b64442fbb06fc 100644 --- a/packages/core/src/linker/ng_module_factory_registration.ts +++ b/packages/core/src/linker/ng_module_factory_registration.ts @@ -50,7 +50,7 @@ export function registerNgModuleType(ngModuleType: NgModuleType) { imports = imports(); } if (imports) { - imports.forEach((i: NgModuleType) => registerNgModuleType(i)); + imports.forEach(i => registerNgModuleType(i as NgModuleType)); } } diff --git a/packages/core/src/metadata/ng_module.ts b/packages/core/src/metadata/ng_module.ts index 0b7638f0ada5f..28b8dcbeefd20 100644 --- a/packages/core/src/metadata/ng_module.ts +++ b/packages/core/src/metadata/ng_module.ts @@ -320,7 +320,7 @@ export const NgModule: NgModuleDecorator = makeDecorator( * * The `imports` and `exports` options bring in members from other modules, and make * this module's members available to others. */ - (type: NgModuleType, meta: NgModule) => SWITCH_COMPILE_NGMODULE(type, meta)); + (type: Type, meta: NgModule) => SWITCH_COMPILE_NGMODULE(type, meta)); /** * @description @@ -344,13 +344,13 @@ export const NgModule: NgModuleDecorator = makeDecorator( */ export interface DoBootstrap { ngDoBootstrap(appRef: ApplicationRef): void; } -function preR3NgModuleCompile(moduleType: InjectorType, metadata: NgModule): void { +function preR3NgModuleCompile(moduleType: Type, metadata?: NgModule): void { let imports = (metadata && metadata.imports) || []; if (metadata && metadata.exports) { imports = [...imports, metadata.exports]; } - moduleType.ngInjectorDef = ɵɵdefineInjector({ + (moduleType as InjectorType).ngInjectorDef = ɵɵdefineInjector({ factory: convertInjectableProviderToFactory(moduleType, {useClass: moduleType}), providers: metadata && metadata.providers, imports: imports, diff --git a/packages/core/src/render3/definition.ts b/packages/core/src/render3/definition.ts index 287654bbf9ea9..1c0e75365383c 100644 --- a/packages/core/src/render3/definition.ts +++ b/packages/core/src/render3/definition.ts @@ -273,7 +273,7 @@ export function ɵɵdefineComponent(componentDefinition: { pipeDefs: null !, // assigned in noSideEffects selectors: componentDefinition.selectors, viewQuery: componentDefinition.viewQuery || null, - features: componentDefinition.features || 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. @@ -324,8 +324,7 @@ export function ɵɵsetComponentScope( def.pipeDefs = () => pipes.map(extractPipeDef); } -export function extractDirectiveDef(type: DirectiveType& ComponentType): - DirectiveDef|ComponentDef { +export function extractDirectiveDef(type: Type): DirectiveDef|ComponentDef { const def = getComponentDef(type) || getDirectiveDef(type); if (ngDevMode && !def) { throw new Error(`'${type.name}' is neither 'ComponentType' or 'DirectiveType'.`); @@ -333,7 +332,7 @@ export function extractDirectiveDef(type: DirectiveType& ComponentType return def !; } -export function extractPipeDef(type: PipeType): PipeDef { +export function extractPipeDef(type: Type): PipeDef { const def = getPipeDef(type); if (ngDevMode && !def) { throw new Error(`'${type.name}' is not a 'PipeType'.`); diff --git a/packages/core/src/render3/di.ts b/packages/core/src/render3/di.ts index 4524988b82122..d5a1a2ef51bff 100644 --- a/packages/core/src/render3/di.ts +++ b/packages/core/src/render3/di.ts @@ -556,7 +556,7 @@ export function getNodeInjectable( const saveLView = getLView(); setTNodeAndViewData(tNode, lData); try { - value = lData[index] = factory.factory(null, tData, lData, tNode); + value = lData[index] = factory.factory(undefined, tData, lData, tNode); } finally { if (factory.injectImpl) setInjectImplementation(previousInjectImplementation); setIncludeViewProviders(previousIncludeViewProviders); diff --git a/packages/core/src/render3/di_setup.ts b/packages/core/src/render3/di_setup.ts index 286f734e1be91..f0b7ef43b8972 100644 --- a/packages/core/src/render3/di_setup.ts +++ b/packages/core/src/render3/di_setup.ts @@ -204,7 +204,8 @@ function indexOf(item: any, arr: any[], begin: number, end: number) { * Use this with `multi` `providers`. */ function multiProvidersFactoryResolver( - this: NodeInjectorFactory, _: null, tData: TData, lData: LView, tNode: TElementNode): any[] { + this: NodeInjectorFactory, _: undefined, tData: TData, lData: LView, + tNode: TElementNode): any[] { return multiResolve(this.multi !, []); } @@ -214,7 +215,8 @@ function multiProvidersFactoryResolver( * This factory knows how to concatenate itself with the existing `multi` `providers`. */ function multiViewProvidersFactoryResolver( - this: NodeInjectorFactory, _: null, tData: TData, lData: LView, tNode: TElementNode): any[] { + this: NodeInjectorFactory, _: undefined, tData: TData, lData: LView, + tNode: TElementNode): any[] { const factories = this.multi !; let result: any[]; if (this.providerFactory) { @@ -252,7 +254,8 @@ function multiResolve(factories: Array<() => any>, result: any[]): any[] { */ function multiFactory( factoryFn: ( - this: NodeInjectorFactory, _: null, tData: TData, lData: LView, tNode: TElementNode) => any, + this: NodeInjectorFactory, _: undefined, tData: TData, lData: LView, tNode: TElementNode) => + any, index: number, isViewProvider: boolean, isComponent: boolean, f: () => any): NodeInjectorFactory { const factory = new NodeInjectorFactory(factoryFn, isViewProvider, ɵɵdirectiveInject); diff --git a/packages/core/src/render3/instructions/shared.ts b/packages/core/src/render3/instructions/shared.ts index 021a0ca8a3720..3712d3919f066 100644 --- a/packages/core/src/render3/instructions/shared.ts +++ b/packages/core/src/render3/instructions/shared.ts @@ -20,7 +20,7 @@ import {diPublicInInjector, getNodeInjectable, getOrCreateNodeInjectorForNode} f import {throwMultipleComponentError} from '../errors'; import {executeHooks, executePreOrderHooks, registerPreOrderHooks} from '../hooks'; import {ACTIVE_INDEX, CONTAINER_HEADER_OFFSET, LContainer} from '../interfaces/container'; -import {ComponentDef, ComponentTemplate, DirectiveDef, DirectiveDefListOrFactory, PipeDefListOrFactory, RenderFlags, ViewQueriesFunction} from '../interfaces/definition'; +import {ComponentDef, ComponentTemplate, DirectiveDef, DirectiveDefListOrFactory, FactoryFn, PipeDefListOrFactory, RenderFlags, ViewQueriesFunction} from '../interfaces/definition'; import {INJECTOR_BLOOM_PARENT_SIZE, NodeInjectorFactory} from '../interfaces/injector'; import {AttributeMarker, InitialInputData, InitialInputs, LocalRefExtractor, PropertyAliasValue, PropertyAliases, TAttributes, TContainerNode, TElementContainerNode, TElementNode, TIcuContainerNode, TNode, TNodeFlags, TNodeProviderIndexes, TNodeType, TProjectionNode, TViewNode} from '../interfaces/node'; import {LQueries} from '../interfaces/query'; @@ -1288,8 +1288,7 @@ export function initNodeFlags(tNode: TNode, index: number, numberOfDirectives: n } function baseResolveDirective( - tView: TView, viewData: LView, def: DirectiveDef, - directiveFactory: (t: Type| null) => any) { + tView: TView, viewData: LView, def: DirectiveDef, directiveFactory: FactoryFn) { tView.data.push(def); const nodeInjectorFactory = new NodeInjectorFactory(directiveFactory, isComponentDef(def), null); tView.blueprint.push(nodeInjectorFactory); diff --git a/packages/core/src/render3/interfaces/injector.ts b/packages/core/src/render3/interfaces/injector.ts index 5fc27c72fe023..e524ce38d40ad 100644 --- a/packages/core/src/render3/interfaces/injector.ts +++ b/packages/core/src/render3/interfaces/injector.ts @@ -132,7 +132,7 @@ export class NodeInjectorFactory { /** * The inject implementation to be activated when using the factory. */ - injectImpl: null|((token: Type|InjectionToken, flags: InjectFlags) => T); + injectImpl: null|((token: Type|InjectionToken, flags?: InjectFlags) => T); /** * Marker set to true during factory invocation to see if we get into recursive loop. @@ -216,7 +216,7 @@ export class NodeInjectorFactory { * Factory to invoke in order to create a new instance. */ public factory: - (this: NodeInjectorFactory, _: null, + (this: NodeInjectorFactory, _: undefined, /** * array where injectables tokens are stored. This is used in * case of an error reporting to produce friendlier errors. @@ -234,8 +234,8 @@ export class NodeInjectorFactory { /** * Set to `true` if the token is declared in `viewProviders` (or if it is component). */ - isViewProvider: boolean, - injectImplementation: null|((token: Type|InjectionToken, flags: InjectFlags) => T)) { + isViewProvider: boolean, injectImplementation: null| + ((token: Type|InjectionToken, flags?: InjectFlags) => T)) { this.canSeeViewProviders = isViewProvider; this.injectImpl = injectImplementation; } diff --git a/packages/core/src/render3/pipe.ts b/packages/core/src/render3/pipe.ts index 43a1939127c99..02a2794b6c3ea 100644 --- a/packages/core/src/render3/pipe.ts +++ b/packages/core/src/render3/pipe.ts @@ -166,7 +166,7 @@ export function ɵɵpipeBind4( * * @codeGenApi */ -export function ɵɵpipeBindV(index: number, slotOffset: number, values: any[]): any { +export function ɵɵpipeBindV(index: number, slotOffset: number, values: [any, ...any[]]): any { const pipeInstance = ɵɵload(index); return unwrapValue( isPure(index) ? ɵɵpureFunctionV(slotOffset, pipeInstance.transform, values, pipeInstance) : diff --git a/packages/core/src/render3/styling/host_instructions_queue.ts b/packages/core/src/render3/styling/host_instructions_queue.ts index e5045cd9e79da..f4682aaf0cf17 100644 --- a/packages/core/src/render3/styling/host_instructions_queue.ts +++ b/packages/core/src/render3/styling/host_instructions_queue.ts @@ -61,7 +61,7 @@ function findNextInsertionIndex(buffer: HostInstructionsQueue, priority: number) * Iterates through the host instructions queue (if present within the provided * context) and executes each queued instruction entry. */ -export function flushQueue(context: StylingContext): void { +export function flushQueue(this: unknown, context: StylingContext): void { const buffer = context[StylingIndex.HostInstructionsQueue]; if (buffer) { for (let i = HostInstructionsQueueIndex.ValuesStartPosition; i < buffer.length; diff --git a/packages/core/src/render3/styling_next/styling_debug.ts b/packages/core/src/render3/styling_next/styling_debug.ts index 2f78274321bf7..926ba8044b0aa 100644 --- a/packages/core/src/render3/styling_next/styling_debug.ts +++ b/packages/core/src/render3/styling_next/styling_debug.ts @@ -201,7 +201,7 @@ export class NodeStylingDebug implements DebugStyling { return entries; } - private _mapValues(fn: (prop: string, value: any, bindingIndex: number|null) => any) { + private _mapValues(fn: (prop: string, value: string|null, bindingIndex: number|null) => any) { // there is no need to store/track an element instance. The // element is only used when the styling algorithm attempts to // style the value (and we mock out the stylingApplyFn anyway). @@ -212,9 +212,8 @@ export class NodeStylingDebug implements DebugStyling { } const mapFn: ApplyStylingFn = - (renderer: any, element: RElement, prop: string, value: any, bindingIndex: number) => { - fn(prop, value, bindingIndex || null); - }; + (renderer: any, element: RElement, prop: string, value: string | null, + bindingIndex?: number | null) => { fn(prop, value, bindingIndex || null); }; const sanitizer = this._isClassBased ? null : (this._sanitizer || getCurrentOrLViewSanitizer(this._data as LView)); diff --git a/packages/core/src/render3/styling_next/util.ts b/packages/core/src/render3/styling_next/util.ts index 494738403afe0..9708910c7e70e 100644 --- a/packages/core/src/render3/styling_next/util.ts +++ b/packages/core/src/render3/styling_next/util.ts @@ -163,10 +163,10 @@ export function getCurrentOrLViewSanitizer(lView: LView): StyleSanitizeFn|null { * sanitization. */ const sanitizeUsingSanitizerObject: StyleSanitizeFn = - (prop: string, value: string, mode: StyleSanitizeMode) => { + (prop: string, value: string | null, mode?: StyleSanitizeMode) => { const sanitizer = getCurrentStyleSanitizer() as Sanitizer; if (sanitizer) { - if (mode & StyleSanitizeMode.SanitizeOnly) { + if (mode !== undefined && mode & StyleSanitizeMode.SanitizeOnly) { return sanitizer.sanitize(SecurityContext.STYLE, value); } else { return true; diff --git a/packages/core/src/util/decorators.ts b/packages/core/src/util/decorators.ts index f19c4e9852fac..c6cb35b7f42c3 100644 --- a/packages/core/src/util/decorators.ts +++ b/packages/core/src/util/decorators.ts @@ -46,10 +46,11 @@ export function makeDecorator( {new (...args: any[]): any; (...args: any[]): any; (...args: any[]): (cls: any) => any;} { const metaCtor = makeMetadataCtor(props); - function DecoratorFactory(...args: any[]): (cls: Type) => any { + function DecoratorFactory( + this: unknown | typeof DecoratorFactory, ...args: any[]): (cls: Type) => any { if (this instanceof DecoratorFactory) { metaCtor.call(this, ...args); - return this; + return this as typeof DecoratorFactory; } const annotationInstance = new (DecoratorFactory as any)(...args); @@ -79,7 +80,7 @@ export function makeDecorator( } function makeMetadataCtor(props?: (...args: any[]) => any): any { - return function ctor(...args: any[]) { + return function ctor(this: any, ...args: any[]) { if (props) { const values = props(...args); for (const propName in values) { @@ -92,7 +93,8 @@ function makeMetadataCtor(props?: (...args: any[]) => any): any { export function makeParamDecorator( name: string, props?: (...args: any[]) => any, parentClass?: any): any { const metaCtor = makeMetadataCtor(props); - function ParamDecoratorFactory(...args: any[]): any { + function ParamDecoratorFactory( + this: unknown | typeof ParamDecoratorFactory, ...args: any[]): any { if (this instanceof ParamDecoratorFactory) { metaCtor.apply(this, args); return this; @@ -132,7 +134,7 @@ export function makePropDecorator( additionalProcessing?: (target: any, name: string, ...args: any[]) => void): any { const metaCtor = makeMetadataCtor(props); - function PropDecoratorFactory(...args: any[]): any { + function PropDecoratorFactory(this: unknown | typeof PropDecoratorFactory, ...args: any[]): any { if (this instanceof PropDecoratorFactory) { metaCtor.apply(this, args); return this; diff --git a/packages/core/src/zone/ng_zone.ts b/packages/core/src/zone/ng_zone.ts index eb79ab04dad45..98b5a6aade001 100644 --- a/packages/core/src/zone/ng_zone.ts +++ b/packages/core/src/zone/ng_zone.ts @@ -267,7 +267,7 @@ function forkInnerZoneWithAngularBehavior(zone: NgZonePrivate) { onInvoke: (delegate: ZoneDelegate, current: Zone, target: Zone, callback: Function, - applyThis: any, applyArgs: any[], source: string): any => { + applyThis: any, applyArgs?: any[], source?: string): any => { try { onEnter(zone); return delegate.invoke(target, callback, applyThis, applyArgs, source); diff --git a/packages/core/test/render3/render_util.ts b/packages/core/test/render3/render_util.ts index da2ff926bc140..ef7d51ae53793 100644 --- a/packages/core/test/render3/render_util.ts +++ b/packages/core/test/render3/render_util.ts @@ -302,7 +302,7 @@ function toDefs( types: PipeTypesOrFactory | undefined | null, mapFn: (type: Type) => PipeDef): PipeDefList|null; function toDefs( - types: PipeTypesOrFactory | DirectiveTypesOrFactory | undefined | null, + types: Type[] | (() => Type[]) | undefined | null, mapFn: (type: Type) => PipeDef| DirectiveDef): any { if (!types) return null; if (typeof types == 'function') { diff --git a/packages/core/test/render3/styling/class_and_style_bindings_spec.ts b/packages/core/test/render3/styling/class_and_style_bindings_spec.ts index c39b62f5fb731..99a59b0f82665 100644 --- a/packages/core/test/render3/styling/class_and_style_bindings_spec.ts +++ b/packages/core/test/render3/styling/class_and_style_bindings_spec.ts @@ -3104,7 +3104,6 @@ describe('style and class based bindings', () => { static ngComponentDef = ɵɵdefineComponent({ type: Comp, selectors: [['comp']], - directives: [Comp], factory: () => new Comp(), consts: 1, vars: 0, @@ -3178,7 +3177,6 @@ describe('style and class based bindings', () => { static ngComponentDef = ɵɵdefineComponent({ type: Comp, selectors: [['comp']], - directives: [Comp], factory: () => new Comp(), consts: 1, vars: 0, @@ -3275,7 +3273,7 @@ describe('style and class based bindings', () => { static ngComponentDef = ɵɵdefineComponent({ type: Comp, selectors: [['comp']], - directives: [Comp, MyDir], + directives: [MyDir], factory: () => new Comp(), consts: 1, vars: 0, diff --git a/packages/core/testing/src/async_fallback.ts b/packages/core/testing/src/async_fallback.ts index 2fa447f7a6bc3..514c4c1241d76 100644 --- a/packages/core/testing/src/async_fallback.ts +++ b/packages/core/testing/src/async_fallback.ts @@ -36,7 +36,7 @@ export function asyncFallback(fn: Function): (done: any) => any { // function when asynchronous activity is finished. if (_global.jasmine) { // Not using an arrow function to preserve context passed from call site - return function(done: any) { + return function(this: unknown, done: any) { if (!done) { // if we run beforeEach in @angular/core/testing/testing_internal then we get no done // fake it here and assume sync. @@ -56,7 +56,7 @@ export function asyncFallback(fn: Function): (done: any) => any { // is finished. This will be correctly consumed by the Mocha framework with // it('...', async(myFn)); or can be used in a custom framework. // Not using an arrow function to preserve context passed from call site - return function() { + return function(this: unknown) { return new Promise((finishCallback, failCallback) => { runInTestZone(fn, this, finishCallback, failCallback); }); diff --git a/packages/core/testing/src/fake_async_fallback.ts b/packages/core/testing/src/fake_async_fallback.ts index 592b87f6cb230..dd08df64eff59 100644 --- a/packages/core/testing/src/fake_async_fallback.ts +++ b/packages/core/testing/src/fake_async_fallback.ts @@ -55,7 +55,7 @@ let _inFakeAsyncCall = false; */ export function fakeAsyncFallback(fn: Function): (...args: any[]) => any { // Not using an arrow function to preserve context passed from call site - return function(...args: any[]) { + return function(this: unknown, ...args: any[]) { const proxyZoneSpec = ProxyZoneSpec.assertPresent(); if (_inFakeAsyncCall) { throw new Error('fakeAsync() calls can not be nested'); diff --git a/packages/core/testing/src/r3_test_bed_compiler.ts b/packages/core/testing/src/r3_test_bed_compiler.ts index 7b710cecd535e..c18d5a7451e3e 100644 --- a/packages/core/testing/src/r3_test_bed_compiler.ts +++ b/packages/core/testing/src/r3_test_bed_compiler.ts @@ -517,20 +517,21 @@ export class R3TestBedCompiler { op.def[op.field] = op.original; } // Restore initial component/directive/pipe defs - this.initialNgDefs.forEach((value: [string, PropertyDescriptor], type: Type) => { - const [prop, descriptor] = value; - if (!descriptor) { - // Delete operations are generally undesirable since they have performance implications - // on objects they were applied to. In this particular case, situations where this code is - // invoked should be quite rare to cause any noticable impact, since it's applied only to - // some test cases (for example when class with no annotations extends some @Component) - // when we need to clear 'ngComponentDef' field on a given class to restore its original - // state (before applying overrides and running tests). - delete (type as any)[prop]; - } else { - Object.defineProperty(type, prop, descriptor); - } - }); + this.initialNgDefs.forEach( + (value: [string, PropertyDescriptor | undefined], type: Type) => { + const [prop, descriptor] = value; + if (!descriptor) { + // Delete operations are generally undesirable since they have performance implications + // on objects they were applied to. In this particular case, situations where this code + // is invoked should be quite rare to cause any noticeable impact, since it's applied + // only to some test cases (for example when class with no annotations extends some + // @Component) when we need to clear 'ngComponentDef' field on a given class to restore + // its original state (before applying overrides and running tests). + delete (type as any)[prop]; + } else { + Object.defineProperty(type, prop, descriptor); + } + }); this.initialNgDefs.clear(); this.moduleProvidersOverridden.clear(); this.restoreComponentResolutionQueue(); diff --git a/packages/core/testing/src/test_bed.ts b/packages/core/testing/src/test_bed.ts index 6fe51195c9d3a..1c8b81ffa0ff3 100644 --- a/packages/core/testing/src/test_bed.ts +++ b/packages/core/testing/src/test_bed.ts @@ -654,7 +654,7 @@ export function inject(tokens: any[], fn: Function): () => any { const testBed = getTestBed(); if (tokens.indexOf(AsyncTestCompleter) >= 0) { // Not using an arrow function to preserve context passed from call site - return function() { + return function(this: unknown) { // Return an async test method that returns a Promise if AsyncTestCompleter is one of // the injected tokens. return testBed.compileComponents().then(() => { @@ -665,7 +665,7 @@ export function inject(tokens: any[], fn: Function): () => any { }; } else { // Not using an arrow function to preserve context passed from call site - return function() { return testBed.execute(tokens, fn, this); }; + return function(this: unknown) { return testBed.execute(tokens, fn, this); }; } } @@ -685,7 +685,7 @@ export class InjectSetupWrapper { inject(tokens: any[], fn: Function): () => any { const self = this; // Not using an arrow function to preserve context passed from call site - return function() { + return function(this: unknown) { self._addModule(); return inject(tokens, fn).call(this); }; @@ -701,7 +701,7 @@ export function withModule(moduleDef: TestModuleMetadata, fn?: Function | null): InjectSetupWrapper { if (fn) { // Not using an arrow function to preserve context passed from call site - return function() { + return function(this: unknown) { const testBed = getTestBed(); if (moduleDef) { testBed.configureTestingModule(moduleDef); diff --git a/packages/core/testing/src/testing_internal.ts b/packages/core/testing/src/testing_internal.ts index 1620e2d71828d..00ce5136ab06b 100644 --- a/packages/core/testing/src/testing_internal.ts +++ b/packages/core/testing/src/testing_internal.ts @@ -39,6 +39,8 @@ const globalTimeOut = jasmine.DEFAULT_TIMEOUT_INTERVAL; const testBed = getTestBed(); +export type TestFn = ((done: DoneFn) => any) | (() => any); + /** * Mechanism to run `beforeEach()` functions of Angular tests. * @@ -112,8 +114,7 @@ export function beforeEachProviders(fn: Function): void { } -function _it( - jsmFn: Function, testName: string, testFn: (done?: DoneFn) => any, testTimeout = 0): void { +function _it(jsmFn: Function, testName: string, testFn: TestFn, testTimeout = 0): void { if (runnerStack.length == 0) { // This left here intentionally, as we should never get here, and it aids debugging. // tslint:disable-next-line @@ -135,7 +136,9 @@ function _it( runner.run(); if (testFn.length === 0) { - const retVal = testFn(); + // TypeScript doesn't infer the TestFn type without parameters here, so we + // need to manually cast it. + const retVal = (testFn as() => any)(); if (isPromise(retVal)) { // Asynchronous test function that returns a Promise - wait for completion. retVal.then(done, done.fail); @@ -150,15 +153,15 @@ function _it( }, timeout); } -export function it(expectation: string, assertion: (done: DoneFn) => any, timeout?: number): void { +export function it(expectation: string, assertion: TestFn, timeout?: number): void { return _it(jsmIt, expectation, assertion, timeout); } -export function fit(expectation: string, assertion: (done: DoneFn) => any, timeout?: number): void { +export function fit(expectation: string, assertion: TestFn, timeout?: number): void { return _it(jsmFIt, expectation, assertion, timeout); } -export function xit(expectation: string, assertion: (done: DoneFn) => any, timeout?: number): void { +export function xit(expectation: string, assertion: TestFn, timeout?: number): void { return _it(jsmXIt, expectation, assertion, timeout); } diff --git a/packages/tsconfig-build-no-strict.json b/packages/tsconfig-build-no-strict.json new file mode 100644 index 0000000000000..c8f428a8f79af --- /dev/null +++ b/packages/tsconfig-build-no-strict.json @@ -0,0 +1,10 @@ +{ + "extends": "./tsconfig-build.json", + "compilerOptions": { + "strict": false + }, + "bazelOptions": { + "suppressTsconfigOverrideWarnings": true, + "devmodeTargetOverride": "es5" + } +} diff --git a/packages/tsconfig-build.json b/packages/tsconfig-build.json index 4db639d949527..e9793106ccf24 100644 --- a/packages/tsconfig-build.json +++ b/packages/tsconfig-build.json @@ -9,6 +9,7 @@ "stripInternal": true, "noImplicitAny": true, "strictNullChecks": true, + "strict": true, "strictPropertyInitialization": true, "noFallthroughCasesInSwitch": true, "moduleResolution": "node", diff --git a/packages/tsconfig-test.json b/packages/tsconfig-test.json index 903117e846576..4ca48743cc64a 100644 --- a/packages/tsconfig-test.json +++ b/packages/tsconfig-test.json @@ -4,11 +4,12 @@ { "extends": "./tsconfig-build.json", "compilerOptions": { + "strict": false, "types": ["node", "jasmine"], "plugins": [{ "name": "@bazel/tsetse", - "disabledRules": ["must-use-promises"], - }], + "disabledRules": ["must-use-promises"] + }] }, "bazelOptions": { "suppressTsconfigOverrideWarnings": true, diff --git a/tools/public_api_guard/core/core.d.ts b/tools/public_api_guard/core/core.d.ts index 4cb2a1c521fdc..898fab9134317 100644 --- a/tools/public_api_guard/core/core.d.ts +++ b/tools/public_api_guard/core/core.d.ts @@ -950,7 +950,7 @@ export declare function ɵɵpipeBind3(index: number, slotOffset: number, v1: any export declare function ɵɵpipeBind4(index: number, slotOffset: number, v1: any, v2: any, v3: any, v4: any): any; -export declare function ɵɵpipeBindV(index: number, slotOffset: number, values: any[]): any; +export declare function ɵɵpipeBindV(index: number, slotOffset: number, values: [any, ...any[]]): any; export declare type ɵɵPipeDefWithMeta = PipeDef;