From e116816131262ac3de6864648a7d483567b06321 Mon Sep 17 00:00:00 2001 From: JoostK Date: Mon, 2 Dec 2019 21:39:11 +0100 Subject: [PATCH] refactor(ivy): let `strictTemplates` imply `fullTemplateTypeCheck` (#34195) Previously, it was required that both `fullTemplateTypeCheck` and `strictTemplates` had to be enabled for strict mode to be enabled. This is strange, as `strictTemplates` implies `fullTemplateTypeCheck`. This commit makes setting the `fullTemplateTypeCheck` flag optional so that strict mode can be enabled by just setting `strictTemplates`. PR Close #34195 --- aio/content/guide/template-typecheck.md | 2 +- packages/compiler-cli/src/ngtsc/program.ts | 13 ++++++--- .../test/ngtsc/template_typecheck_spec.ts | 27 +++++++++---------- 3 files changed, 22 insertions(+), 20 deletions(-) diff --git a/aio/content/guide/template-typecheck.md b/aio/content/guide/template-typecheck.md index c985fa879b..39b13dd0ec 100644 --- a/aio/content/guide/template-typecheck.md +++ b/aio/content/guide/template-typecheck.md @@ -46,7 +46,7 @@ The following still have type `any`. ### Strict mode Angular version 9 maintains the behavior of the `fullTemplateTypeCheck` flag, and introduces a third "strict mode". -Strict mode is accessed by setting both `fullTemplateTypeCheck` and the `strictTemplates` flag to `true`. +Strict mode is a superset of full mode, and is accessed by setting the `strictTemplates` flag to true. This flag supersedes the `fullTemplateTypeCheck` flag. In strict mode, Angular version 9 adds checks that go beyond the version 8 type-checker. Note that strict mode is only available if using Ivy. diff --git a/packages/compiler-cli/src/ngtsc/program.ts b/packages/compiler-cli/src/ngtsc/program.ts index 34255a07eb..d086b7f694 100644 --- a/packages/compiler-cli/src/ngtsc/program.ts +++ b/packages/compiler-cli/src/ngtsc/program.ts @@ -462,9 +462,15 @@ export class NgtscProgram implements api.Program { } private getTemplateDiagnostics(): ReadonlyArray { + // Determine the strictness level of type checking based on compiler options. As + // `strictTemplates` is a superset of `fullTemplateTypeCheck`, the former implies the latter. + // Also see `verifyCompatibleTypeCheckOptions` where it is verified that `fullTemplateTypeCheck` + // is not disabled when `strictTemplates` is enabled. + const strictTemplates = !!this.options.strictTemplates; + const fullTemplateTypeCheck = strictTemplates || !!this.options.fullTemplateTypeCheck; + // Skip template type-checking if it's disabled. - if (this.options.ivyTemplateTypeCheck === false && - this.options.fullTemplateTypeCheck !== true) { + if (this.options.ivyTemplateTypeCheck === false && !fullTemplateTypeCheck) { return []; } @@ -475,8 +481,7 @@ export class NgtscProgram implements api.Program { // First select a type-checking configuration, based on whether full template type-checking is // requested. let typeCheckingConfig: TypeCheckingConfig; - if (this.options.fullTemplateTypeCheck) { - const strictTemplates = !!this.options.strictTemplates; + if (fullTemplateTypeCheck) { typeCheckingConfig = { applyTemplateContextGuards: strictTemplates, checkQueries: false, diff --git a/packages/compiler-cli/test/ngtsc/template_typecheck_spec.ts b/packages/compiler-cli/test/ngtsc/template_typecheck_spec.ts index 0a2cc9d64b..543f106218 100644 --- a/packages/compiler-cli/test/ngtsc/template_typecheck_spec.ts +++ b/packages/compiler-cli/test/ngtsc/template_typecheck_spec.ts @@ -245,7 +245,7 @@ export declare class AnimationEvent { }); it('should check expressions and their type when overall strictness is enabled', () => { - env.tsconfig({fullTemplateTypeCheck: true, strictTemplates: true}); + env.tsconfig({strictTemplates: true}); const diags = env.driveDiagnostics(); expect(diags.length).toBe(2); @@ -303,7 +303,7 @@ export declare class AnimationEvent { it('should check expressions and their nullability when overall strictness is enabled', () => { - env.tsconfig({fullTemplateTypeCheck: true, strictTemplates: true}); + env.tsconfig({strictTemplates: true}); const diags = env.driveDiagnostics(); expect(diags.length).toBe(2); @@ -366,10 +366,7 @@ export declare class AnimationEvent { it('should infer result type for safe navigation expressions when overall strictness is enabled', () => { - env.tsconfig({ - fullTemplateTypeCheck: true, - strictTemplates: true, - }); + env.tsconfig({strictTemplates: true}); const diags = env.driveDiagnostics(); expect(diags.length).toBe(2); @@ -429,7 +426,7 @@ export declare class AnimationEvent { }); it('should expressions and infer type of $event when overall strictness is enabled', () => { - env.tsconfig({fullTemplateTypeCheck: true, strictTemplates: true}); + env.tsconfig({strictTemplates: true}); const diags = env.driveDiagnostics(); expect(diags.length).toBe(2); @@ -483,7 +480,7 @@ export declare class AnimationEvent { it('should check expressions and let $event be of type AnimationEvent when overall strictness is enabled', () => { - env.tsconfig({fullTemplateTypeCheck: true, strictTemplates: true}); + env.tsconfig({strictTemplates: true}); const diags = env.driveDiagnostics(); expect(diags.length).toBe(2); @@ -532,7 +529,7 @@ export declare class AnimationEvent { }); it('should infer the type of DOM references when overall strictness is enabled', () => { - env.tsconfig({fullTemplateTypeCheck: true, strictTemplates: true}); + env.tsconfig({strictTemplates: true}); const diags = env.driveDiagnostics(); expect(diags.length).toBe(1); @@ -583,7 +580,7 @@ export declare class AnimationEvent { }); it('should produce an error for text attributes when overall strictness is enabled', () => { - env.tsconfig({fullTemplateTypeCheck: true, strictTemplates: true}); + env.tsconfig({strictTemplates: true}); const diags = env.driveDiagnostics(); expect(diags.length).toBe(2); @@ -633,7 +630,7 @@ export declare class AnimationEvent { it('should check expressions and infer type of $event when overall strictness is enabled', () => { - env.tsconfig({fullTemplateTypeCheck: true, strictTemplates: true}); + env.tsconfig({strictTemplates: true}); const diags = env.driveDiagnostics(); expect(diags.length).toBe(2); @@ -776,7 +773,7 @@ export declare class AnimationEvent { }); it('should accept NgFor iteration over a QueryList', () => { - env.tsconfig({fullTemplateTypeCheck: true, strictTemplates: true}); + env.tsconfig({strictTemplates: true}); env.write('test.ts', ` import {CommonModule} from '@angular/common'; import {Component, NgModule, QueryList} from '@angular/core'; @@ -800,7 +797,7 @@ export declare class AnimationEvent { }); it('should infer the context of NgFor', () => { - env.tsconfig({fullTemplateTypeCheck: true, strictTemplates: true}); + env.tsconfig({strictTemplates: true}); env.write('test.ts', ` import {CommonModule} from '@angular/common'; import {Component, NgModule} from '@angular/core'; @@ -825,7 +822,7 @@ export declare class AnimationEvent { }); it('should infer the context of NgIf', () => { - env.tsconfig({fullTemplateTypeCheck: true, strictTemplates: true}); + env.tsconfig({strictTemplates: true}); env.write('test.ts', ` import {CommonModule} from '@angular/common'; import {Component, NgModule} from '@angular/core'; @@ -1009,7 +1006,7 @@ export declare class AnimationEvent { }); it('should be correctly inferred under strictTemplates', () => { - env.tsconfig({fullTemplateTypeCheck: true, strictTemplates: true}); + env.tsconfig({strictTemplates: true}); const diags = env.driveDiagnostics(); expect(diags.length).toBe(1);