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 4c33356b82..0e5160830a 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 @@ -6,7 +6,7 @@ * found in the LICENSE file at https://angular.io/license */ -import {AST, BindingPipe, BindingType, BoundTarget, ImplicitReceiver, PropertyRead, TmplAstBoundAttribute, TmplAstBoundText, TmplAstElement, TmplAstNode, TmplAstReference, TmplAstTemplate, TmplAstTextAttribute, TmplAstVariable} from '@angular/compiler'; +import {AST, BindingPipe, BindingType, BoundTarget, ImplicitReceiver, MethodCall, PropertyRead, TmplAstBoundAttribute, TmplAstBoundText, TmplAstElement, TmplAstNode, TmplAstReference, TmplAstTemplate, TmplAstTextAttribute, TmplAstVariable} from '@angular/compiler'; import * as ts from 'typescript'; import {Reference} from '../../imports'; @@ -813,6 +813,13 @@ function tcbResolve(ast: AST, tcb: Context, scope: Scope): ts.Expression|null { } const args = ast.args.map(arg => tcbExpression(arg, tcb, scope)); return tsCallMethod(pipe, 'transform', [expr, ...args]); + } else if ( + ast instanceof MethodCall && ast.receiver instanceof ImplicitReceiver && + ast.name === '$any' && ast.args.length === 1) { + const expr = tcbExpression(ast.args[0], tcb, scope); + const exprAsAny = + ts.createAsExpression(expr, ts.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword)); + return ts.createParen(exprAsAny); } else { // This AST isn't special after all. return 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 8c76a07326..c4538dd9a7 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 @@ -76,6 +76,12 @@ describe('type check blocks', () => { expect(block).not.toContain('.style = '); }); + it('should handle $any casts', () => { + const TEMPLATE = `{{$any(a)}}`; + const block = tcb(TEMPLATE); + expect(block).toContain('(ctx.a as any);'); + }); + describe('config', () => { const DIRECTIVES: TestDeclaration[] = [{ type: 'directive',