diff --git a/packages/compiler-cli/src/ngtsc/program.ts b/packages/compiler-cli/src/ngtsc/program.ts index 963d4c448c..50f3cc06fd 100644 --- a/packages/compiler-cli/src/ngtsc/program.ts +++ b/packages/compiler-cli/src/ngtsc/program.ts @@ -431,6 +431,7 @@ export class NgtscProgram implements api.Program { checkTemplateBodies: true, checkTypeOfInputBindings: true, strictNullInputBindings: true, + checkTypeOfAttributes: true, // Even in full template type-checking mode, DOM binding checks are not quite ready yet. checkTypeOfDomBindings: false, checkTypeOfOutputEvents: true, @@ -451,6 +452,7 @@ export class NgtscProgram implements api.Program { checkTemplateBodies: false, checkTypeOfInputBindings: false, strictNullInputBindings: false, + checkTypeOfAttributes: false, checkTypeOfDomBindings: false, checkTypeOfOutputEvents: false, checkTypeOfAnimationEvents: false, diff --git a/packages/compiler-cli/src/ngtsc/typecheck/src/api.ts b/packages/compiler-cli/src/ngtsc/typecheck/src/api.ts index c2ccc6bab3..77e2464792 100644 --- a/packages/compiler-cli/src/ngtsc/typecheck/src/api.ts +++ b/packages/compiler-cli/src/ngtsc/typecheck/src/api.ts @@ -98,9 +98,24 @@ export interface TypeCheckingConfig { * binding expressions are wrapped in a non-null assertion operator to effectively disable strict * null checks. This may be particularly useful when the directive is from a library that is not * compiled with `strictNullChecks` enabled. + * + * If `checkTypeOfInputBindings` is set to `false`, this flag has no effect. */ strictNullInputBindings: boolean; + /** + * Whether to check text attributes that happen to be consumed by a directive or component. + * + * For example, in a template containing `` the `disabled` attribute ends + * up being consumed as an input with type `boolean` by the `matInput` directive. At runtime the + * input will be set to the attribute's string value, which is the empty string for attributes + * without a value, so with this flag set to `true` an error would be reported. If set to `false`, + * text attributes will never report an error. + * + * Note that if `checkTypeOfInputBindings` is set to `false`, this flag has no effect. + */ + checkTypeOfAttributes: boolean; + /** * Whether to check the left-hand side type of binding operations to DOM properties. * diff --git a/packages/compiler-cli/src/ngtsc/typecheck/src/type_check_block.ts b/packages/compiler-cli/src/ngtsc/typecheck/src/type_check_block.ts index cd8cb476d4..e28e93d2c0 100644 --- a/packages/compiler-cli/src/ngtsc/typecheck/src/type_check_block.ts +++ b/packages/compiler-cli/src/ngtsc/typecheck/src/type_check_block.ts @@ -1153,6 +1153,11 @@ function tcbGetDirectiveInputs( return; } + // Skip text attributes if configured to do so. + if (!tcb.env.config.checkTypeOfAttributes && attr instanceof TmplAstTextAttribute) { + return; + } + // Skip the attribute if the directive does not have an input for it. if (!propMatch.has(attr.name)) { return; diff --git a/packages/compiler-cli/src/ngtsc/typecheck/test/diagnostics_spec.ts b/packages/compiler-cli/src/ngtsc/typecheck/test/diagnostics_spec.ts index 8d0fddd32a..8cedeb585e 100644 --- a/packages/compiler-cli/src/ngtsc/typecheck/test/diagnostics_spec.ts +++ b/packages/compiler-cli/src/ngtsc/typecheck/test/diagnostics_spec.ts @@ -154,6 +154,25 @@ runInEachFileSystem(() => { ]); }); + it('checks text attributes that are consumed by bindings with literal string types', () => { + const messages = diagnose( + `
`, ` + class Dir { + mode: 'dark'|'light'; + } + class TestComponent {}`, + [{ + type: 'directive', + name: 'Dir', + selector: '[dir]', + inputs: {'mode': 'mode'}, + }]); + + expect(messages).toEqual([ + `synthetic.html(1, 10): Type '"drak"' is not assignable to type '"dark" | "light"'.`, + ]); + }); + it('produces diagnostics for pipes', () => { const messages = diagnose( `