diff --git a/modules/@angular/compiler/src/output/output_ast.ts b/modules/@angular/compiler/src/output/output_ast.ts index 8e1dc59ef2..9b2dd5bb79 100644 --- a/modules/@angular/compiler/src/output/output_ast.ts +++ b/modules/@angular/compiler/src/output/output_ast.ts @@ -32,7 +32,8 @@ export enum BuiltinTypeName { String, Int, Number, - Function + Function, + Null } export class BuiltinType extends Type { @@ -73,7 +74,7 @@ export var INT_TYPE = new BuiltinType(BuiltinTypeName.Int); export var NUMBER_TYPE = new BuiltinType(BuiltinTypeName.Number); export var STRING_TYPE = new BuiltinType(BuiltinTypeName.String); export var FUNCTION_TYPE = new BuiltinType(BuiltinTypeName.Function); - +export var NULL_TYPE = new BuiltinType(BuiltinTypeName.Null); export interface TypeVisitor { visitBuiltintType(type: BuiltinType, context: any): any; @@ -175,7 +176,8 @@ export abstract class Expression { } isBlank(): Expression { // Note: We use equals by purpose here to compare to null and undefined in JS. - return this.equals(NULL_EXPR); + // We use the typed null to allow strictNullChecks to narrow types. + return this.equals(TYPED_NULL_EXPR); } cast(type: Type): Expression { return new CastExpr(this, type); } toStmt(): Statement { return new ExpressionStatement(this); } @@ -451,6 +453,7 @@ export var SUPER_EXPR = new ReadVarExpr(BuiltinVar.Super); export var CATCH_ERROR_VAR = new ReadVarExpr(BuiltinVar.CatchError); export var CATCH_STACK_VAR = new ReadVarExpr(BuiltinVar.CatchStack); export var NULL_EXPR = new LiteralExpr(null, null); +export var TYPED_NULL_EXPR = new LiteralExpr(null, NULL_TYPE); //// Statements export enum StmtModifier { diff --git a/modules/@angular/compiler/src/output/ts_emitter.ts b/modules/@angular/compiler/src/output/ts_emitter.ts index 8f9c2fb262..49c502d320 100644 --- a/modules/@angular/compiler/src/output/ts_emitter.ts +++ b/modules/@angular/compiler/src/output/ts_emitter.ts @@ -69,7 +69,7 @@ class _TsEmitterVisitor extends AbstractEmitterVisitor implements o.TypeVisitor visitLiteralExpr(ast: o.LiteralExpr, ctx: EmitterVisitorContext): any { const value = ast.value; - if (isBlank(value)) { + if (isBlank(value) && ast.type != o.NULL_TYPE) { ctx.print(`(${value} as any)`); return null; } diff --git a/modules/@angular/compiler/test/output/ts_emitter_spec.ts b/modules/@angular/compiler/test/output/ts_emitter_spec.ts index b750ba6106..32c6537770 100644 --- a/modules/@angular/compiler/test/output/ts_emitter_spec.ts +++ b/modules/@angular/compiler/test/output/ts_emitter_spec.ts @@ -110,6 +110,7 @@ export function main() { it('should support blank literals', () => { expect(emitStmt(o.literal(null).toStmt())).toEqual('(null as any);'); expect(emitStmt(o.literal(undefined).toStmt())).toEqual('(undefined as any);'); + expect(emitStmt(o.variable('a', null).isBlank().toStmt())).toEqual('(a == null);'); }); it('should support external identifiers', () => {