diff --git a/packages/compiler-cli/src/ngtsc/typecheck/src/expression.ts b/packages/compiler-cli/src/ngtsc/typecheck/src/expression.ts index e9b3973012..7839a77dda 100644 --- a/packages/compiler-cli/src/ngtsc/typecheck/src/expression.ts +++ b/packages/compiler-cli/src/ngtsc/typecheck/src/expression.ts @@ -6,7 +6,7 @@ * found in the LICENSE file at https://angular.io/license */ -import {AST, ASTWithSource, AstVisitor, Binary, BindingPipe, Chain, Conditional, FunctionCall, ImplicitReceiver, Interpolation, KeyedRead, KeyedWrite, LiteralArray, LiteralMap, LiteralPrimitive, MethodCall, NonNullAssert, ParseSpan, PrefixNot, PropertyRead, PropertyWrite, Quote, SafeMethodCall, SafePropertyRead} from '@angular/compiler'; +import {AST, ASTWithSource, AstVisitor, Binary, BindingPipe, Chain, Conditional, EmptyExpr, FunctionCall, ImplicitReceiver, Interpolation, KeyedRead, KeyedWrite, LiteralArray, LiteralMap, LiteralPrimitive, MethodCall, NonNullAssert, ParseSpan, PrefixNot, PropertyRead, PropertyWrite, Quote, SafeMethodCall, SafePropertyRead} from '@angular/compiler'; import * as ts from 'typescript'; import {TypeCheckingConfig} from './api'; @@ -60,6 +60,11 @@ class AstTranslator implements AstVisitor { ast = ast.ast; } + // The `EmptyExpr` doesn't have a dedicated method on `AstVisitor`, so it's special cased here. + if (ast instanceof EmptyExpr) { + return UNDEFINED; + } + // First attempt to let any custom resolution logic provide a translation for the given node. const resolved = this.maybeResolve(ast); if (resolved !== null) { 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 1d6848e6c3..103081c83b 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 @@ -39,6 +39,16 @@ describe('type check blocks', () => { expect(tcb(TEMPLATE)).toContain('_t1.htmlFor = ("test");'); }); + it('should handle empty bindings', () => { + const TEMPLATE = ``; + expect(tcb(TEMPLATE)).toContain('_t1.type = (undefined);'); + }); + + it('should handle bindings without value', () => { + const TEMPLATE = ``; + expect(tcb(TEMPLATE)).toContain('_t1.type = (undefined);'); + }); + it('should handle implicit vars on ng-template', () => { const TEMPLATE = ``; expect(tcb(TEMPLATE)).toContain('var _t2 = _t1.$implicit;');