feat(compiler): support a non-null postfix assert (#16672)

Template expressions can now use a post-fix `!` operator
that asserts the target of the operator is not null. This is
similar to the TypeScript non-null assert operator. Expressions
generated in factories will be generated with the non-null assert
operator.

Closes: #10855
This commit is contained in:
Chuck Jazdzewski
2017-05-11 10:15:54 -07:00
committed by Jason Aden
parent 2eca6e67e1
commit b9521b568f
16 changed files with 122 additions and 5 deletions

View File

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
import {AST, AstVisitor, Binary, BindingPipe, Chain, Conditional, FunctionCall, ImplicitReceiver, Interpolation, KeyedRead, KeyedWrite, LiteralArray, LiteralMap, LiteralPrimitive, MethodCall, PrefixNot, PropertyRead, PropertyWrite, Quote, SafeMethodCall, SafePropertyRead, visitAstChildren} from '@angular/compiler';
import {AST, AstVisitor, Binary, BindingPipe, Chain, Conditional, FunctionCall, ImplicitReceiver, Interpolation, KeyedRead, KeyedWrite, LiteralArray, LiteralMap, LiteralPrimitive, MethodCall, NonNullAssert, PrefixNot, PropertyRead, PropertyWrite, Quote, SafeMethodCall, SafePropertyRead, visitAstChildren} from '@angular/compiler';
import {BuiltinType, Signature, Span, Symbol, SymbolQuery, SymbolTable} from './symbols';
@ -283,6 +283,11 @@ export class AstType implements AstVisitor {
return this.query.getBuiltinType(BuiltinType.Boolean);
}
visitNonNullAssert(ast: NonNullAssert) {
const expressionType = this.getType(ast.expression);
return this.query.getNonNullableType(expressionType);
}
visitPropertyRead(ast: PropertyRead) {
return this.resolvePropertyRead(this.getType(ast.receiver), ast);
}

View File

@ -135,6 +135,8 @@ describe('expression diagnostics', () => {
() => reject(`<div>{{maybe_person.name.first}}`, 'The expression might be null'));
it('should accept a safe accss to an undefined field',
() => accept(`<div>{{maybe_person?.name.first}}</div>`));
it('should accept a type assert to an undefined field',
() => accept(`<div>{{maybe_person!.name.first}}</div>`));
it('should accept a # reference', () => accept(`
<form #f="ngForm" novalidate>
<input name="first" ngModel required #first="ngModel">