diff --git a/packages/compiler-cli/src/ngtsc/typecheck/src/type_constructor.ts b/packages/compiler-cli/src/ngtsc/typecheck/src/type_constructor.ts index 139ec6a232..f80fd0fc69 100644 --- a/packages/compiler-cli/src/ngtsc/typecheck/src/type_constructor.ts +++ b/packages/compiler-cli/src/ngtsc/typecheck/src/type_constructor.ts @@ -166,8 +166,8 @@ function constructTypeCtorParameter( if (coercedKeys.length > 0) { const coercedLiteral = ts.createTypeLiteralNode(coercedKeys); - initType = - initType !== null ? ts.createUnionTypeNode([initType, coercedLiteral]) : coercedLiteral; + initType = initType !== null ? ts.createIntersectionTypeNode([initType, coercedLiteral]) : + coercedLiteral; } if (initType === null) { diff --git a/packages/compiler-cli/src/ngtsc/typecheck/test/type_constructor_spec.ts b/packages/compiler-cli/src/ngtsc/typecheck/test/type_constructor_spec.ts index 54c399f1ba..f490cda7f5 100644 --- a/packages/compiler-cli/src/ngtsc/typecheck/test/type_constructor_spec.ts +++ b/packages/compiler-cli/src/ngtsc/typecheck/test/type_constructor_spec.ts @@ -179,7 +179,7 @@ TestClass.ngTypeCtor({value: 'test'}); const typeCtor = TestClassWithCtor.members.find(isTypeCtor)!; const ctorText = typeCtor.getText().replace(/[ \r\n]+/g, ' '); expect(ctorText).toContain( - 'init: Pick | { bar: typeof TestClass.ngAcceptInputType_bar; }'); + 'init: Pick & { bar: typeof TestClass.ngAcceptInputType_bar; }'); }); }); }); diff --git a/packages/compiler-cli/test/ngtsc/template_typecheck_spec.ts b/packages/compiler-cli/test/ngtsc/template_typecheck_spec.ts index 377179e736..7c9ec4dbf4 100644 --- a/packages/compiler-cli/test/ngtsc/template_typecheck_spec.ts +++ b/packages/compiler-cli/test/ngtsc/template_typecheck_spec.ts @@ -1498,6 +1498,39 @@ export declare class AnimationEvent { expect(diags[0].messageText) .toBe(`Type 'boolean' is not assignable to type 'string | number'.`); }); + + it('should give an error for undefined bindings into regular inputs when coercion members are present', + () => { + env.tsconfig({strictTemplates: true}); + env.write('test.ts', ` + import {Component, Directive, NgModule, Input} from '@angular/core'; + + @Component({ + selector: 'blah', + template: '', + }) + export class FooCmp { + invalidType = true; + } + + @Directive({selector: '[dir]'}) + export class CoercionDir { + @Input() regular: string; + @Input() coerced: boolean; + + static ngAcceptInputType_coerced: boolean|number; + } + + @NgModule({ + declarations: [FooCmp, CoercionDir], + }) + export class FooModule {} + `); + const diags = env.driveDiagnostics(); + expect(diags.length).toBe(1); + expect(diags[0].messageText) + .toBe(`Type 'undefined' is not assignable to type 'string'.`); + }); }); describe('legacy schema checking with the DOM schema', () => {