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 0d417fae78..0410b72bc5 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 @@ -1622,7 +1622,7 @@ class TcbExpressionTranslator { return null; } - const method = ts.createPropertyAccess(wrapForDiagnostics(receiver), ast.name); + const method = wrapForDiagnostics(receiver); addParseSpanInfo(method, ast.nameSpan); const args = ast.args.map(arg => this.translate(arg)); const node = ts.createCall(method, undefined, args); diff --git a/packages/compiler-cli/src/ngtsc/typecheck/test/span_comments_spec.ts b/packages/compiler-cli/src/ngtsc/typecheck/test/span_comments_spec.ts index caa312ce0a..6d8236e23e 100644 --- a/packages/compiler-cli/src/ngtsc/typecheck/test/span_comments_spec.ts +++ b/packages/compiler-cli/src/ngtsc/typecheck/test/span_comments_spec.ts @@ -71,7 +71,7 @@ describe('type check blocks diagnostics', () => { const TEMPLATE = `{{ method(a, b) }}`; expect(tcbWithSpans(TEMPLATE)) .toContain( - '(_t2 /*27,39*/).method /*27,33*/(((ctx).a /*34,35*/) /*34,35*/, ((ctx).b /*37,38*/) /*37,38*/) /*27,39*/'); + '(_t2 /*27,39*/) /*27,33*/(((ctx).a /*34,35*/) /*34,35*/, ((ctx).b /*37,38*/) /*37,38*/) /*27,39*/'); }); it('should annotate function calls', () => { diff --git a/packages/compiler-cli/src/ngtsc/typecheck/test/type_check_block_spec.ts b/packages/compiler-cli/src/ngtsc/typecheck/test/type_check_block_spec.ts index f81ac38469..82fc1d0583 100644 --- a/packages/compiler-cli/src/ngtsc/typecheck/test/type_check_block_spec.ts +++ b/packages/compiler-cli/src/ngtsc/typecheck/test/type_check_block_spec.ts @@ -106,7 +106,7 @@ describe('type check blocks', () => { it('should handle method calls of template variables', () => { const TEMPLATE = `{{a(1)}}`; expect(tcb(TEMPLATE)).toContain('var _t2 = _t1.$implicit;'); - expect(tcb(TEMPLATE)).toContain('(_t2).a(1)'); + expect(tcb(TEMPLATE)).toContain('(_t2)(1)'); }); it('should handle implicit vars when using microsyntax', () => { @@ -114,6 +114,12 @@ describe('type check blocks', () => { expect(tcb(TEMPLATE)).toContain('var _t2 = _t1.$implicit;'); }); + it('should handle direct calls of an implicit template variable', () => { + const TEMPLATE = `
{{a(1)}}
`; + expect(tcb(TEMPLATE)).toContain('var _t2 = _t1.$implicit;'); + expect(tcb(TEMPLATE)).toContain('(_t2)(1)'); + }); + describe('type constructors', () => { it('should handle missing property bindings', () => { const TEMPLATE = `
`; diff --git a/packages/compiler-cli/test/ngtsc/template_typecheck_spec.ts b/packages/compiler-cli/test/ngtsc/template_typecheck_spec.ts index 4e20f958ec..80d0f20199 100644 --- a/packages/compiler-cli/test/ngtsc/template_typecheck_spec.ts +++ b/packages/compiler-cli/test/ngtsc/template_typecheck_spec.ts @@ -1009,6 +1009,30 @@ export declare class AnimationEvent { expect(diags.length).toBe(0); }); + it('should allow the implicit value of an NgFor to be invoked', () => { + env.tsconfig({fullTemplateTypeCheck: true, strictInputTypes: true}); + env.write('test.ts', ` + import {CommonModule} from '@angular/common'; + import {Component, NgModule} from '@angular/core'; + + @Component({ + selector: 'test', + template: '
{{fn()}}
', + }) + class TestCmp { + functions = [() => 1, () => 2]; + } + + @NgModule({ + declarations: [TestCmp], + imports: [CommonModule], + }) + class Module {} + `); + + env.driveMain(); + }); + it('should infer the context of NgIf', () => { env.tsconfig({strictTemplates: true}); env.write('test.ts', `