diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index fc08a862007..21c5d14db1d 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -1883,6 +1883,7 @@ namespace ts { case SyntaxKind.EnumMember: case SyntaxKind.TypeAssertionExpression: case SyntaxKind.AsExpression: + case SyntaxKind.NonNullExpression: case SyntaxKind.ReadonlyKeyword: // These nodes are TypeScript syntax. transformFlags = TransformFlags.AssertTypeScript; diff --git a/src/compiler/printer.ts b/src/compiler/printer.ts index 2410785d897..501b03425df 100644 --- a/src/compiler/printer.ts +++ b/src/compiler/printer.ts @@ -751,6 +751,8 @@ const _super = (function (geti, seti) { return; case SyntaxKind.AsExpression: return emitAsExpression(node); + case SyntaxKind.NonNullExpression: + return emitNonNullExpression(node); // JSX case SyntaxKind.JsxElement: @@ -1286,6 +1288,11 @@ const _super = (function (geti, seti) { } } + function emitNonNullExpression(node: NonNullExpression) { + emitExpression(node.expression); + write("!"); + } + // // Misc // diff --git a/src/compiler/transformers/ts.ts b/src/compiler/transformers/ts.ts index d5b969926cc..7eb10f7342e 100644 --- a/src/compiler/transformers/ts.ts +++ b/src/compiler/transformers/ts.ts @@ -372,6 +372,10 @@ namespace ts { // TypeScript type assertions are removed, but their subtrees are preserved. return visitAssertionExpression(node); + case SyntaxKind.NonNullExpression: + // TypeScript non-null expressions are removed, but their subtrees are preserved. + return visitNonNullExpression(node); + case SyntaxKind.EnumDeclaration: // TypeScript enum declarations do not exist in ES6 and must be rewritten. return visitEnumDeclaration(node); @@ -2233,7 +2237,12 @@ namespace ts { } function visitAssertionExpression(node: AssertionExpression): Expression { - const expression = visitNode((node).expression, visitor, isExpression); + const expression = visitNode(node.expression, visitor, isExpression); + return createPartiallyEmittedExpression(expression, node); + } + + function visitNonNullExpression(node: NonNullExpression): Expression { + const expression = visitNode(node.expression, visitor, isLeftHandSideExpression); return createPartiallyEmittedExpression(expression, node); } diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 7e393c5a35a..31e4277f75f 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -509,7 +509,7 @@ namespace ts { const { line: startLine } = getLineAndCharacterOfPosition(sourceFile, node.body.pos); const { line: endLine } = getLineAndCharacterOfPosition(sourceFile, node.body.end); if (startLine < endLine) { - // The arrow function spans multiple lines, + // The arrow function spans multiple lines, // make the error span be the first line, inclusive. return createTextSpan(pos, getEndLinePosition(startLine, sourceFile) - pos + 1); } @@ -3462,7 +3462,8 @@ namespace ts { || kind === SyntaxKind.NullKeyword || kind === SyntaxKind.ThisKeyword || kind === SyntaxKind.TrueKeyword - || kind === SyntaxKind.SuperKeyword; + || kind === SyntaxKind.SuperKeyword + || kind === SyntaxKind.NonNullExpression; } export function isLeftHandSideExpression(node: Node): node is LeftHandSideExpression { diff --git a/src/compiler/visitor.ts b/src/compiler/visitor.ts index d55357bed8d..525761df5c3 100644 --- a/src/compiler/visitor.ts +++ b/src/compiler/visitor.ts @@ -219,6 +219,9 @@ namespace ts { { name: "expression", test: isExpression }, { name: "type", test: isTypeNode } ], + [SyntaxKind.NonNullExpression]: [ + { name: "expression", test: isLeftHandSideExpression } + ], [SyntaxKind.TemplateSpan]: [ { name: "expression", test: isExpression }, { name: "literal", test: isTemplateLiteralFragment }