feat(ivy): type-checking for some previously unsupported expressions (#29698)
This commit adds support for the generation of type-checking expressions for forms which were previously unsupported: * array literals * map literals * keyed property accesses * non-null assertions Testing strategy: TCB tests included. Fixes #29327 FW-1218 #resolve PR Close #29698
This commit is contained in:
parent
e3d5d41140
commit
9f5288dad3
|
@ -6,7 +6,7 @@
|
|||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {AST, ASTWithSource, Binary, Conditional, Interpolation, LiteralPrimitive, MethodCall, PropertyRead} from '@angular/compiler';
|
||||
import {AST, ASTWithSource, Binary, Conditional, Interpolation, KeyedRead, LiteralArray, LiteralMap, LiteralPrimitive, MethodCall, NonNullAssert, PropertyRead} from '@angular/compiler';
|
||||
import * as ts from 'typescript';
|
||||
|
||||
const BINARY_OPS = new Map<string, ts.SyntaxKind>([
|
||||
|
@ -76,6 +76,22 @@ export function astToTypescript(
|
|||
const trueExpr = astToTypescript(ast.trueExp, maybeResolve);
|
||||
const falseExpr = astToTypescript(ast.falseExp, maybeResolve);
|
||||
return ts.createParen(ts.createConditional(condExpr, trueExpr, falseExpr));
|
||||
} else if (ast instanceof LiteralArray) {
|
||||
const elements = ast.expressions.map(expr => astToTypescript(expr, maybeResolve));
|
||||
return ts.createArrayLiteral(elements);
|
||||
} else if (ast instanceof LiteralMap) {
|
||||
const properties = ast.keys.map(({key}, idx) => {
|
||||
const value = astToTypescript(ast.values[idx], maybeResolve);
|
||||
return ts.createPropertyAssignment(ts.createStringLiteral(key), value);
|
||||
});
|
||||
return ts.createObjectLiteral(properties, true);
|
||||
} else if (ast instanceof KeyedRead) {
|
||||
const receiver = astToTypescript(ast.obj, maybeResolve);
|
||||
const key = astToTypescript(ast.key, maybeResolve);
|
||||
return ts.createElementAccess(receiver, key);
|
||||
} else if (ast instanceof NonNullAssert) {
|
||||
const expr = astToTypescript(ast.expression, maybeResolve);
|
||||
return ts.createNonNullExpression(expr);
|
||||
} else {
|
||||
throw new Error(`Unknown node type: ${Object.getPrototypeOf(ast).constructor}`);
|
||||
}
|
||||
|
|
|
@ -19,6 +19,26 @@ import {generateTypeCheckBlock} from '../src/type_check_block';
|
|||
describe('type check blocks', () => {
|
||||
it('should generate a basic block for a binding',
|
||||
() => { expect(tcb('{{hello}}')).toContain('ctx.hello;'); });
|
||||
|
||||
it('should generate literal map expressions', () => {
|
||||
const TEMPLATE = '{{ method({foo: a, bar: b}) }}';
|
||||
expect(tcb(TEMPLATE)).toContain('ctx.method({ "foo": ctx.a, "bar": ctx.b });');
|
||||
});
|
||||
|
||||
it('should generate literal array expressions', () => {
|
||||
const TEMPLATE = '{{ method([a, b]) }}';
|
||||
expect(tcb(TEMPLATE)).toContain('ctx.method([ctx.a, ctx.b]);');
|
||||
});
|
||||
|
||||
it('should handle non-null assertions', () => {
|
||||
const TEMPLATE = `{{a!}}`;
|
||||
expect(tcb(TEMPLATE)).toContain('ctx.a!;');
|
||||
});
|
||||
|
||||
it('should handle keyed property access', () => {
|
||||
const TEMPLATE = `{{a[b]}}`;
|
||||
expect(tcb(TEMPLATE)).toContain('ctx.a[ctx.b];');
|
||||
});
|
||||
});
|
||||
|
||||
function getClass(sf: ts.SourceFile, name: string): ClassDeclaration<ts.ClassDeclaration> {
|
||||
|
|
Loading…
Reference in New Issue