From 20f59871a8fd0522002ca75731152c3389db8179 Mon Sep 17 00:00:00 2001 From: Ryan Cavanaugh Date: Mon, 18 May 2015 08:12:00 -0700 Subject: [PATCH 01/12] 'as' operator --- src/compiler/checker.ts | 12 +++++++++++ src/compiler/parser.ts | 19 +++++++++++++++++- src/compiler/types.ts | 7 +++++++ tests/baselines/reference/APISample_linter.js | 18 ++++++++--------- tests/baselines/reference/asOperator1.js | 12 +++++++++++ tests/baselines/reference/asOperator1.symbols | 15 ++++++++++++++ tests/baselines/reference/asOperator1.types | 20 +++++++++++++++++++ .../expressions/asOperator/asOperator1.ts | 4 ++++ 8 files changed, 97 insertions(+), 10 deletions(-) create mode 100644 tests/baselines/reference/asOperator1.js create mode 100644 tests/baselines/reference/asOperator1.symbols create mode 100644 tests/baselines/reference/asOperator1.types create mode 100644 tests/cases/conformance/expressions/asOperator/asOperator1.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 5d26a30c3b7dd..417a58c632287 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -7264,6 +7264,16 @@ module ts { function checkTypeAssertion(node: TypeAssertion): Type { let exprType = checkExpression(node.expression); let targetType = getTypeFromTypeNode(node.type); + return checkAssertion(node, exprType, targetType); + } + + function checkAsExpression(node: AsExpression) { + let exprType = checkExpression(node.left); + let targetType = getTypeFromTypeNode(node.right); + return checkAssertion(node, exprType, targetType); + } + + function checkAssertion(node: Node, exprType: Type, targetType: Type) { if (produceDiagnostics && targetType !== unknownType) { let widenedType = getWidenedType(exprType); if (!(isTypeAssignableTo(targetType, widenedType))) { @@ -8145,6 +8155,8 @@ module ts { return checkFunctionExpressionOrObjectLiteralMethod(node, contextualMapper); case SyntaxKind.TypeOfExpression: return checkTypeOfExpression(node); + case SyntaxKind.AsExpression: + return checkAsExpression(node); case SyntaxKind.DeleteExpression: return checkDeleteExpression(node); case SyntaxKind.VoidExpression: diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index af9b486a1da4f..c653c0e208bed 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -159,6 +159,10 @@ module ts { return visitNode(cbNode, (node).left) || visitNode(cbNode, (node).operatorToken) || visitNode(cbNode, (node).right); + case SyntaxKind.AsExpression: + return visitNode(cbNode, (node).left) || + visitNode(cbNode, (node).asToken) || + visitNode(cbNode, (node).right); case SyntaxKind.ConditionalExpression: return visitNode(cbNode, (node).condition) || visitNode(cbNode, (node).questionToken) || @@ -2818,7 +2822,11 @@ module ts { break; } - leftOperand = makeBinaryExpression(leftOperand, parseTokenNode(), parseBinaryExpressionOrHigher(newPrecedence)); + if (token === SyntaxKind.AsKeyword) { + leftOperand = makeAsExpression(leftOperand, parseTokenNode(), parseType()); + } else { + leftOperand = makeBinaryExpression(leftOperand, parseTokenNode(), parseBinaryExpressionOrHigher(newPrecedence)); + } } return leftOperand; @@ -2855,6 +2863,7 @@ module ts { case SyntaxKind.GreaterThanEqualsToken: case SyntaxKind.InstanceOfKeyword: case SyntaxKind.InKeyword: + case SyntaxKind.AsKeyword: return 7; case SyntaxKind.LessThanLessThanToken: case SyntaxKind.GreaterThanGreaterThanToken: @@ -2882,6 +2891,14 @@ module ts { return finishNode(node); } + function makeAsExpression(left: Expression, operatorToken: Node, right: TypeNode): AsExpression { + let node = createNode(SyntaxKind.AsExpression, left.pos); + node.left = left; + node.asToken = operatorToken; + node.right = right; + return finishNode(node); + } + function parsePrefixUnaryExpression() { let node = createNode(SyntaxKind.PrefixUnaryExpression); node.operator = token; diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 86e680ca8b047..1bb22fdf7ba80 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -207,6 +207,7 @@ module ts { ClassExpression, OmittedExpression, ExpressionWithTypeArguments, + AsExpression, // Misc TemplateSpan, SemicolonClassElement, @@ -669,6 +670,12 @@ module ts { right: Expression; } + export interface AsExpression extends Expression { + left: Expression; + asToken: Node; + right: TypeNode; + } + export interface ConditionalExpression extends Expression { condition: Expression; questionToken: Node; diff --git a/tests/baselines/reference/APISample_linter.js b/tests/baselines/reference/APISample_linter.js index cd2df23ffbf4f..9582fbaa528e8 100644 --- a/tests/baselines/reference/APISample_linter.js +++ b/tests/baselines/reference/APISample_linter.js @@ -75,22 +75,22 @@ function delint(sourceFile) { delintNode(sourceFile); function delintNode(node) { switch (node.kind) { - case 187 /* ForStatement */: - case 188 /* ForInStatement */: - case 186 /* WhileStatement */: - case 185 /* DoStatement */: - if (node.statement.kind !== 180 /* Block */) { + case 188 /* ForStatement */: + case 189 /* ForInStatement */: + case 187 /* WhileStatement */: + case 186 /* DoStatement */: + if (node.statement.kind !== 181 /* Block */) { report(node, "A looping statement's contents should be wrapped in a block body."); } break; - case 184 /* IfStatement */: + case 185 /* IfStatement */: var ifStatement = node; - if (ifStatement.thenStatement.kind !== 180 /* Block */) { + if (ifStatement.thenStatement.kind !== 181 /* Block */) { report(ifStatement.thenStatement, "An if statement's contents should be wrapped in a block body."); } if (ifStatement.elseStatement && - ifStatement.elseStatement.kind !== 180 /* Block */ && - ifStatement.elseStatement.kind !== 184 /* IfStatement */) { + ifStatement.elseStatement.kind !== 181 /* Block */ && + ifStatement.elseStatement.kind !== 185 /* IfStatement */) { report(ifStatement.elseStatement, "An else statement's contents should be wrapped in a block body."); } break; diff --git a/tests/baselines/reference/asOperator1.js b/tests/baselines/reference/asOperator1.js new file mode 100644 index 0000000000000..8fef05284ab37 --- /dev/null +++ b/tests/baselines/reference/asOperator1.js @@ -0,0 +1,12 @@ +//// [asOperator1.ts] +var as = 43; +var x = undefined as number; +var y = (null as string).length; +var z = Date as any as string; + + +//// [asOperator1.js] +var as = 43; +var x = ; +var y = ().length; +var z = ; diff --git a/tests/baselines/reference/asOperator1.symbols b/tests/baselines/reference/asOperator1.symbols new file mode 100644 index 0000000000000..a695fe02b5def --- /dev/null +++ b/tests/baselines/reference/asOperator1.symbols @@ -0,0 +1,15 @@ +=== tests/cases/conformance/expressions/asOperator/asOperator1.ts === +var as = 43; +>as : Symbol(as, Decl(asOperator1.ts, 0, 3)) + +var x = undefined as number; +>x : Symbol(x, Decl(asOperator1.ts, 1, 3)) + +var y = (null as string).length; +>y : Symbol(y, Decl(asOperator1.ts, 2, 3)) +>(null as string).length : Symbol(String.length, Decl(lib.d.ts, 414, 19)) +>length : Symbol(String.length, Decl(lib.d.ts, 414, 19)) + +var z = Date as any as string; +>z : Symbol(z, Decl(asOperator1.ts, 3, 3)) + diff --git a/tests/baselines/reference/asOperator1.types b/tests/baselines/reference/asOperator1.types new file mode 100644 index 0000000000000..49da534b17be2 --- /dev/null +++ b/tests/baselines/reference/asOperator1.types @@ -0,0 +1,20 @@ +=== tests/cases/conformance/expressions/asOperator/asOperator1.ts === +var as = 43; +>as : number +>43 : number + +var x = undefined as number; +>x : number +>undefined : any + +var y = (null as string).length; +>y : number +>(null as string).length : number +>(null as string) : string +>null : null +>length : number + +var z = Date as any as string; +>z : string +>Date : any + diff --git a/tests/cases/conformance/expressions/asOperator/asOperator1.ts b/tests/cases/conformance/expressions/asOperator/asOperator1.ts new file mode 100644 index 0000000000000..0c811be27b1b2 --- /dev/null +++ b/tests/cases/conformance/expressions/asOperator/asOperator1.ts @@ -0,0 +1,4 @@ +var as = 43; +var x = undefined as number; +var y = (null as string).length; +var z = Date as any as string; From 634cc0ec3362540c6c6cbf4e4f218db791b01478 Mon Sep 17 00:00:00 2001 From: Ryan Cavanaugh Date: Mon, 18 May 2015 08:23:18 -0700 Subject: [PATCH 02/12] Emit for 'as' operator --- src/compiler/emitter.ts | 2 ++ tests/baselines/reference/asOperator1.js | 6 +++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index c9d23ec5ceebf..fe3c71b5cb208 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -5840,6 +5840,8 @@ var __param = (this && this.__param) || function (paramIndex, decorator) { return emitTaggedTemplateExpression(node); case SyntaxKind.TypeAssertionExpression: return emit((node).expression); + case SyntaxKind.AsExpression: + return emit((node).left); case SyntaxKind.ParenthesizedExpression: return emitParenExpression(node); case SyntaxKind.FunctionDeclaration: diff --git a/tests/baselines/reference/asOperator1.js b/tests/baselines/reference/asOperator1.js index 8fef05284ab37..c818eeff9af87 100644 --- a/tests/baselines/reference/asOperator1.js +++ b/tests/baselines/reference/asOperator1.js @@ -7,6 +7,6 @@ var z = Date as any as string; //// [asOperator1.js] var as = 43; -var x = ; -var y = ().length; -var z = ; +var x = undefined; +var y = (null).length; +var z = Date; From 8f788481cafa0b5ae84305d860d01bb426bfba24 Mon Sep 17 00:00:00 2001 From: Ryan Cavanaugh Date: Mon, 18 May 2015 08:33:11 -0700 Subject: [PATCH 03/12] Add an error testcase --- tests/baselines/reference/asOperator2.errors.txt | 8 ++++++++ tests/baselines/reference/asOperator2.js | 6 ++++++ .../conformance/expressions/asOperator/asOperator2.ts | 1 + 3 files changed, 15 insertions(+) create mode 100644 tests/baselines/reference/asOperator2.errors.txt create mode 100644 tests/baselines/reference/asOperator2.js create mode 100644 tests/cases/conformance/expressions/asOperator/asOperator2.ts diff --git a/tests/baselines/reference/asOperator2.errors.txt b/tests/baselines/reference/asOperator2.errors.txt new file mode 100644 index 0000000000000..3b074038c26b0 --- /dev/null +++ b/tests/baselines/reference/asOperator2.errors.txt @@ -0,0 +1,8 @@ +tests/cases/conformance/expressions/asOperator/asOperator2.ts(1,9): error TS2352: Neither type 'number' nor type 'string' is assignable to the other. + + +==== tests/cases/conformance/expressions/asOperator/asOperator2.ts (1 errors) ==== + var x = 23 as string; + ~~~~~~~~~~~~ +!!! error TS2352: Neither type 'number' nor type 'string' is assignable to the other. + \ No newline at end of file diff --git a/tests/baselines/reference/asOperator2.js b/tests/baselines/reference/asOperator2.js new file mode 100644 index 0000000000000..32962555d5107 --- /dev/null +++ b/tests/baselines/reference/asOperator2.js @@ -0,0 +1,6 @@ +//// [asOperator2.ts] +var x = 23 as string; + + +//// [asOperator2.js] +var x = 23; diff --git a/tests/cases/conformance/expressions/asOperator/asOperator2.ts b/tests/cases/conformance/expressions/asOperator/asOperator2.ts new file mode 100644 index 0000000000000..1fa5f2c938d78 --- /dev/null +++ b/tests/cases/conformance/expressions/asOperator/asOperator2.ts @@ -0,0 +1 @@ +var x = 23 as string; From 8b0391163413953959df63e171fb589eaa71a937 Mon Sep 17 00:00:00 2001 From: Ryan Cavanaugh Date: Mon, 18 May 2015 11:04:16 -0700 Subject: [PATCH 04/12] PR feedback --- src/compiler/checker.ts | 18 ++---- src/compiler/emitter.ts | 4 +- src/compiler/parser.ts | 15 +++-- src/compiler/types.ts | 4 +- tests/baselines/reference/asOperator3.js | 22 ++++++++ tests/baselines/reference/asOperator3.symbols | 31 +++++++++++ tests/baselines/reference/asOperator3.types | 55 +++++++++++++++++++ .../expressions/asOperator/asOperator3.ts | 10 ++++ 8 files changed, 133 insertions(+), 26 deletions(-) create mode 100644 tests/baselines/reference/asOperator3.js create mode 100644 tests/baselines/reference/asOperator3.symbols create mode 100644 tests/baselines/reference/asOperator3.types create mode 100644 tests/cases/conformance/expressions/asOperator/asOperator3.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 417a58c632287..b1b08d1acf6e9 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -7261,19 +7261,10 @@ module ts { return getReturnTypeOfSignature(getResolvedSignature(node)); } - function checkTypeAssertion(node: TypeAssertion): Type { + + function checkAssertion(node: AsExpression|TypeAssertion) { let exprType = checkExpression(node.expression); let targetType = getTypeFromTypeNode(node.type); - return checkAssertion(node, exprType, targetType); - } - - function checkAsExpression(node: AsExpression) { - let exprType = checkExpression(node.left); - let targetType = getTypeFromTypeNode(node.right); - return checkAssertion(node, exprType, targetType); - } - - function checkAssertion(node: Node, exprType: Type, targetType: Type) { if (produceDiagnostics && targetType !== unknownType) { let widenedType = getWidenedType(exprType); if (!(isTypeAssignableTo(targetType, widenedType))) { @@ -8144,8 +8135,6 @@ module ts { return checkCallExpression(node); case SyntaxKind.TaggedTemplateExpression: return checkTaggedTemplateExpression(node); - case SyntaxKind.TypeAssertionExpression: - return checkTypeAssertion(node); case SyntaxKind.ParenthesizedExpression: return checkExpression((node).expression, contextualMapper); case SyntaxKind.ClassExpression: @@ -8155,8 +8144,9 @@ module ts { return checkFunctionExpressionOrObjectLiteralMethod(node, contextualMapper); case SyntaxKind.TypeOfExpression: return checkTypeOfExpression(node); + case SyntaxKind.TypeAssertionExpression: case SyntaxKind.AsExpression: - return checkAsExpression(node); + return checkAssertion(node); case SyntaxKind.DeleteExpression: return checkDeleteExpression(node); case SyntaxKind.VoidExpression: diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index fe3c71b5cb208..ed05a83c86972 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -1790,7 +1790,7 @@ var __param = (this && this.__param) || function (paramIndex, decorator) { } function skipParentheses(node: Expression): Expression { - while (node.kind === SyntaxKind.ParenthesizedExpression || node.kind === SyntaxKind.TypeAssertionExpression) { + while (node.kind === SyntaxKind.ParenthesizedExpression || node.kind === SyntaxKind.TypeAssertionExpression || node.kind === SyntaxKind.AsExpression) { node = (node).expression; } return node; @@ -5841,7 +5841,7 @@ var __param = (this && this.__param) || function (paramIndex, decorator) { case SyntaxKind.TypeAssertionExpression: return emit((node).expression); case SyntaxKind.AsExpression: - return emit((node).left); + return emit((node).expression); case SyntaxKind.ParenthesizedExpression: return emitParenExpression(node); case SyntaxKind.FunctionDeclaration: diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index c653c0e208bed..ae24f5f003737 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -160,9 +160,8 @@ module ts { visitNode(cbNode, (node).operatorToken) || visitNode(cbNode, (node).right); case SyntaxKind.AsExpression: - return visitNode(cbNode, (node).left) || - visitNode(cbNode, (node).asToken) || - visitNode(cbNode, (node).right); + return visitNode(cbNode, (node).expression) || + visitNode(cbNode, (node).type); case SyntaxKind.ConditionalExpression: return visitNode(cbNode, (node).condition) || visitNode(cbNode, (node).questionToken) || @@ -2823,7 +2822,8 @@ module ts { } if (token === SyntaxKind.AsKeyword) { - leftOperand = makeAsExpression(leftOperand, parseTokenNode(), parseType()); + parseTokenNode(); + leftOperand = makeAsExpression(leftOperand, parseType()); } else { leftOperand = makeBinaryExpression(leftOperand, parseTokenNode(), parseBinaryExpressionOrHigher(newPrecedence)); } @@ -2891,11 +2891,10 @@ module ts { return finishNode(node); } - function makeAsExpression(left: Expression, operatorToken: Node, right: TypeNode): AsExpression { + function makeAsExpression(left: Expression, right: TypeNode): AsExpression { let node = createNode(SyntaxKind.AsExpression, left.pos); - node.left = left; - node.asToken = operatorToken; - node.right = right; + node.expression = left; + node.type = right; return finishNode(node); } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 1bb22fdf7ba80..907f52437862c 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -671,9 +671,9 @@ module ts { } export interface AsExpression extends Expression { - left: Expression; + expression: Expression; asToken: Node; - right: TypeNode; + type: TypeNode; } export interface ConditionalExpression extends Expression { diff --git a/tests/baselines/reference/asOperator3.js b/tests/baselines/reference/asOperator3.js new file mode 100644 index 0000000000000..42181cd87c4a1 --- /dev/null +++ b/tests/baselines/reference/asOperator3.js @@ -0,0 +1,22 @@ +//// [asOperator3.ts] +declare function tag(...x: any[]): any; + +var a = `${123 + 456 as number}`; +var b = `leading ${123 + 456 as number}`; +var c = `${123 + 456 as number} trailing`; +var d = `Hello ${123} World` as string; +var e = `Hello` as string; +var f = 1 + `${1} end of string` as string; +var g = tag `Hello ${123} World` as string; +var h = tag `Hello` as string; + +//// [asOperator3.js] +var a = "" + 123 + 456; +var b = "leading " + 123 + 456; +var c = 123 + 456 + " trailing"; +var d = "Hello " + 123 + " World"; +var e = "Hello"; +var f = 1 + (1 + " end of string"); +var g = (_a = ["Hello ", " World"], _a.raw = ["Hello ", " World"], tag(_a, 123)); +var h = (_b = ["Hello"], _b.raw = ["Hello"], tag(_b)); +var _a, _b; diff --git a/tests/baselines/reference/asOperator3.symbols b/tests/baselines/reference/asOperator3.symbols new file mode 100644 index 0000000000000..d29a64d3c3a51 --- /dev/null +++ b/tests/baselines/reference/asOperator3.symbols @@ -0,0 +1,31 @@ +=== tests/cases/conformance/expressions/asOperator/asOperator3.ts === +declare function tag(...x: any[]): any; +>tag : Symbol(tag, Decl(asOperator3.ts, 0, 0)) +>x : Symbol(x, Decl(asOperator3.ts, 0, 21)) + +var a = `${123 + 456 as number}`; +>a : Symbol(a, Decl(asOperator3.ts, 2, 3)) + +var b = `leading ${123 + 456 as number}`; +>b : Symbol(b, Decl(asOperator3.ts, 3, 3)) + +var c = `${123 + 456 as number} trailing`; +>c : Symbol(c, Decl(asOperator3.ts, 4, 3)) + +var d = `Hello ${123} World` as string; +>d : Symbol(d, Decl(asOperator3.ts, 5, 3)) + +var e = `Hello` as string; +>e : Symbol(e, Decl(asOperator3.ts, 6, 3)) + +var f = 1 + `${1} end of string` as string; +>f : Symbol(f, Decl(asOperator3.ts, 7, 3)) + +var g = tag `Hello ${123} World` as string; +>g : Symbol(g, Decl(asOperator3.ts, 8, 3)) +>tag : Symbol(tag, Decl(asOperator3.ts, 0, 0)) + +var h = tag `Hello` as string; +>h : Symbol(h, Decl(asOperator3.ts, 9, 3)) +>tag : Symbol(tag, Decl(asOperator3.ts, 0, 0)) + diff --git a/tests/baselines/reference/asOperator3.types b/tests/baselines/reference/asOperator3.types new file mode 100644 index 0000000000000..1b3e1c42d1242 --- /dev/null +++ b/tests/baselines/reference/asOperator3.types @@ -0,0 +1,55 @@ +=== tests/cases/conformance/expressions/asOperator/asOperator3.ts === +declare function tag(...x: any[]): any; +>tag : (...x: any[]) => any +>x : any[] + +var a = `${123 + 456 as number}`; +>a : string +>`${123 + 456 as number}` : string +>123 + 456 : number +>123 : number +>456 : number + +var b = `leading ${123 + 456 as number}`; +>b : string +>`leading ${123 + 456 as number}` : string +>123 + 456 : number +>123 : number +>456 : number + +var c = `${123 + 456 as number} trailing`; +>c : string +>`${123 + 456 as number} trailing` : string +>123 + 456 : number +>123 : number +>456 : number + +var d = `Hello ${123} World` as string; +>d : string +>`Hello ${123} World` : string +>123 : number + +var e = `Hello` as string; +>e : string +>`Hello` : string + +var f = 1 + `${1} end of string` as string; +>f : string +>1 + `${1} end of string` : string +>1 : number +>`${1} end of string` : string +>1 : number + +var g = tag `Hello ${123} World` as string; +>g : string +>tag `Hello ${123} World` : any +>tag : (...x: any[]) => any +>`Hello ${123} World` : string +>123 : number + +var h = tag `Hello` as string; +>h : string +>tag `Hello` : any +>tag : (...x: any[]) => any +>`Hello` : string + diff --git a/tests/cases/conformance/expressions/asOperator/asOperator3.ts b/tests/cases/conformance/expressions/asOperator/asOperator3.ts new file mode 100644 index 0000000000000..4c136247e001f --- /dev/null +++ b/tests/cases/conformance/expressions/asOperator/asOperator3.ts @@ -0,0 +1,10 @@ +declare function tag(...x: any[]): any; + +var a = `${123 + 456 as number}`; +var b = `leading ${123 + 456 as number}`; +var c = `${123 + 456 as number} trailing`; +var d = `Hello ${123} World` as string; +var e = `Hello` as string; +var f = 1 + `${1} end of string` as string; +var g = tag `Hello ${123} World` as string; +var h = tag `Hello` as string; \ No newline at end of file From 3aa1caa5e67c22739f5faa1a2ec560871b1b0c4e Mon Sep 17 00:00:00 2001 From: Ryan Cavanaugh Date: Mon, 18 May 2015 11:17:17 -0700 Subject: [PATCH 05/12] Add a type alias for As/old-style assert --- src/compiler/checker.ts | 5 ++--- src/compiler/types.ts | 2 ++ 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index b1b08d1acf6e9..98d8df6a6168f 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -7261,8 +7261,7 @@ module ts { return getReturnTypeOfSignature(getResolvedSignature(node)); } - - function checkAssertion(node: AsExpression|TypeAssertion) { + function checkAssertion(node: AssertionExpression) { let exprType = checkExpression(node.expression); let targetType = getTypeFromTypeNode(node.type); if (produceDiagnostics && targetType !== unknownType) { @@ -8146,7 +8145,7 @@ module ts { return checkTypeOfExpression(node); case SyntaxKind.TypeAssertionExpression: case SyntaxKind.AsExpression: - return checkAssertion(node); + return checkAssertion(node); case SyntaxKind.DeleteExpression: return checkDeleteExpression(node); case SyntaxKind.VoidExpression: diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 907f52437862c..84006a2d89596 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -405,6 +405,8 @@ module ts { export type DeclarationName = Identifier | LiteralExpression | ComputedPropertyName | BindingPattern; + export type AssertionExpression = TypeAssertion | AsExpression; + export interface Declaration extends Node { _declarationBrand: any; name?: DeclarationName; From e1e577de392f50880575f16b78219b93c0ee8b0f Mon Sep 17 00:00:00 2001 From: Ryan Cavanaugh Date: Mon, 18 May 2015 11:17:31 -0700 Subject: [PATCH 06/12] Correctly deparenthesize 'as' exprs --- src/compiler/emitter.ts | 10 +++++----- tests/baselines/reference/asOperator1.js | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index ed05a83c86972..42e8ec7a45e91 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -1791,7 +1791,7 @@ var __param = (this && this.__param) || function (paramIndex, decorator) { function skipParentheses(node: Expression): Expression { while (node.kind === SyntaxKind.ParenthesizedExpression || node.kind === SyntaxKind.TypeAssertionExpression || node.kind === SyntaxKind.AsExpression) { - node = (node).expression; + node = (node).expression; } return node; } @@ -1907,13 +1907,13 @@ var __param = (this && this.__param) || function (paramIndex, decorator) { function emitParenExpression(node: ParenthesizedExpression) { if (!node.parent || node.parent.kind !== SyntaxKind.ArrowFunction) { - if (node.expression.kind === SyntaxKind.TypeAssertionExpression) { - let operand = (node.expression).expression; + if (node.expression.kind === SyntaxKind.TypeAssertionExpression || node.expression.kind === SyntaxKind.AsExpression) { + let operand = (node.expression).expression; // Make sure we consider all nested cast expressions, e.g.: // (-A).x; - while (operand.kind == SyntaxKind.TypeAssertionExpression) { - operand = (operand).expression; + while (operand.kind === SyntaxKind.TypeAssertionExpression || operand.kind === SyntaxKind.AsExpression) { + operand = (operand).expression; } // We have an expression of the form: (SubExpr) diff --git a/tests/baselines/reference/asOperator1.js b/tests/baselines/reference/asOperator1.js index c818eeff9af87..a00d31d31ef97 100644 --- a/tests/baselines/reference/asOperator1.js +++ b/tests/baselines/reference/asOperator1.js @@ -8,5 +8,5 @@ var z = Date as any as string; //// [asOperator1.js] var as = 43; var x = undefined; -var y = (null).length; +var y = null.length; var z = Date; From 1e6bd1c19e97d7c4ea1172f45b393ed49cd102bd Mon Sep 17 00:00:00 2001 From: Ryan Cavanaugh Date: Tue, 19 May 2015 18:04:06 -0700 Subject: [PATCH 07/12] Add formatting for 'as' operator --- src/services/formatting/rules.ts | 1 + src/services/formatting/tokenRange.ts | 2 +- tests/cases/fourslash/asOperatorFormatting.ts | 7 +++++++ 3 files changed, 9 insertions(+), 1 deletion(-) create mode 100644 tests/cases/fourslash/asOperatorFormatting.ts diff --git a/src/services/formatting/rules.ts b/src/services/formatting/rules.ts index 0b6a6ad0bdce2..cf4a08af758c8 100644 --- a/src/services/formatting/rules.ts +++ b/src/services/formatting/rules.ts @@ -457,6 +457,7 @@ module ts.formatting { switch (context.contextNode.kind) { case SyntaxKind.BinaryExpression: case SyntaxKind.ConditionalExpression: + case SyntaxKind.AsExpression: return true; // equals in binding elements: function foo([[x, y] = [1, 2]]) diff --git a/src/services/formatting/tokenRange.ts b/src/services/formatting/tokenRange.ts index 712d6f3792e0d..1936ab3630358 100644 --- a/src/services/formatting/tokenRange.ts +++ b/src/services/formatting/tokenRange.ts @@ -112,7 +112,7 @@ module ts.formatting { static AnyIncludingMultilineComments = TokenRange.FromTokens(TokenRange.Any.GetTokens().concat([SyntaxKind.MultiLineCommentTrivia])); static Keywords = TokenRange.FromRange(SyntaxKind.FirstKeyword, SyntaxKind.LastKeyword); static BinaryOperators = TokenRange.FromRange(SyntaxKind.FirstBinaryOperator, SyntaxKind.LastBinaryOperator); - static BinaryKeywordOperators = TokenRange.FromTokens([SyntaxKind.InKeyword, SyntaxKind.InstanceOfKeyword, SyntaxKind.OfKeyword]); + static BinaryKeywordOperators = TokenRange.FromTokens([SyntaxKind.InKeyword, SyntaxKind.InstanceOfKeyword, SyntaxKind.OfKeyword, SyntaxKind.AsKeyword]); static UnaryPrefixOperators = TokenRange.FromTokens([SyntaxKind.PlusPlusToken, SyntaxKind.MinusMinusToken, SyntaxKind.TildeToken, SyntaxKind.ExclamationToken]); static UnaryPrefixExpressions = TokenRange.FromTokens([SyntaxKind.NumericLiteral, SyntaxKind.Identifier, SyntaxKind.OpenParenToken, SyntaxKind.OpenBracketToken, SyntaxKind.OpenBraceToken, SyntaxKind.ThisKeyword, SyntaxKind.NewKeyword]); static UnaryPreincrementExpressions = TokenRange.FromTokens([SyntaxKind.Identifier, SyntaxKind.OpenParenToken, SyntaxKind.ThisKeyword, SyntaxKind.NewKeyword]); diff --git a/tests/cases/fourslash/asOperatorFormatting.ts b/tests/cases/fourslash/asOperatorFormatting.ts new file mode 100644 index 0000000000000..f697ffd8bb6c2 --- /dev/null +++ b/tests/cases/fourslash/asOperatorFormatting.ts @@ -0,0 +1,7 @@ +/// + +//// /**/var x = 3 as number; + +goTo.marker(); +format.document(); +verify.currentLineContentIs("var x = 3 as number;"); From d5bf6896b2fddfa77879e4fe1d885e159546f974 Mon Sep 17 00:00:00 2001 From: Ryan Cavanaugh Date: Tue, 19 May 2015 18:04:30 -0700 Subject: [PATCH 08/12] Fix ASI for 'as' operator --- src/compiler/parser.ts | 8 ++++-- tests/baselines/reference/asOperatorASI.js | 26 +++++++++++++++++ .../baselines/reference/asOperatorASI.symbols | 23 +++++++++++++++ tests/baselines/reference/asOperatorASI.types | 28 +++++++++++++++++++ .../expressions/asOperator/asOperatorASI.ts | 10 +++++++ 5 files changed, 93 insertions(+), 2 deletions(-) create mode 100644 tests/baselines/reference/asOperatorASI.js create mode 100644 tests/baselines/reference/asOperatorASI.symbols create mode 100644 tests/baselines/reference/asOperatorASI.types create mode 100644 tests/cases/conformance/expressions/asOperator/asOperatorASI.ts diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index ae24f5f003737..3fe334ab1dbe7 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -2822,8 +2822,12 @@ module ts { } if (token === SyntaxKind.AsKeyword) { - parseTokenNode(); - leftOperand = makeAsExpression(leftOperand, parseType()); + if (canParseSemicolon()) { + break; + } else { + parseTokenNode(); + leftOperand = makeAsExpression(leftOperand, parseType()); + } } else { leftOperand = makeBinaryExpression(leftOperand, parseTokenNode(), parseBinaryExpressionOrHigher(newPrecedence)); } diff --git a/tests/baselines/reference/asOperatorASI.js b/tests/baselines/reference/asOperatorASI.js new file mode 100644 index 0000000000000..1df39b36e50f5 --- /dev/null +++ b/tests/baselines/reference/asOperatorASI.js @@ -0,0 +1,26 @@ +//// [asOperatorASI.ts] +class Foo { } +declare function as(...args: any[]); + +// Example 1 +var x = 10 +as `Hello world`; // should not error + +// Example 2 +var y = 20 +as(Foo); // should emit + + +//// [asOperatorASI.js] +var Foo = (function () { + function Foo() { + } + return Foo; +})(); +// Example 1 +var x = 10; +(_a = ["Hello world"], _a.raw = ["Hello world"], as(_a)); // should not error +// Example 2 +var y = 20; +as(Foo); // should emit +var _a; diff --git a/tests/baselines/reference/asOperatorASI.symbols b/tests/baselines/reference/asOperatorASI.symbols new file mode 100644 index 0000000000000..7def6d460c15c --- /dev/null +++ b/tests/baselines/reference/asOperatorASI.symbols @@ -0,0 +1,23 @@ +=== tests/cases/conformance/expressions/asOperator/asOperatorASI.ts === +class Foo { } +>Foo : Symbol(Foo, Decl(asOperatorASI.ts, 0, 0)) + +declare function as(...args: any[]); +>as : Symbol(as, Decl(asOperatorASI.ts, 0, 13)) +>args : Symbol(args, Decl(asOperatorASI.ts, 1, 20)) + +// Example 1 +var x = 10 +>x : Symbol(x, Decl(asOperatorASI.ts, 4, 3)) + +as `Hello world`; // should not error +>as : Symbol(as, Decl(asOperatorASI.ts, 0, 13)) + +// Example 2 +var y = 20 +>y : Symbol(y, Decl(asOperatorASI.ts, 8, 3)) + +as(Foo); // should emit +>as : Symbol(as, Decl(asOperatorASI.ts, 0, 13)) +>Foo : Symbol(Foo, Decl(asOperatorASI.ts, 0, 0)) + diff --git a/tests/baselines/reference/asOperatorASI.types b/tests/baselines/reference/asOperatorASI.types new file mode 100644 index 0000000000000..61c2d115cf4f6 --- /dev/null +++ b/tests/baselines/reference/asOperatorASI.types @@ -0,0 +1,28 @@ +=== tests/cases/conformance/expressions/asOperator/asOperatorASI.ts === +class Foo { } +>Foo : Foo + +declare function as(...args: any[]); +>as : (...args: any[]) => any +>args : any[] + +// Example 1 +var x = 10 +>x : number +>10 : number + +as `Hello world`; // should not error +>as `Hello world` : any +>as : (...args: any[]) => any +>`Hello world` : string + +// Example 2 +var y = 20 +>y : number +>20 : number + +as(Foo); // should emit +>as(Foo) : any +>as : (...args: any[]) => any +>Foo : typeof Foo + diff --git a/tests/cases/conformance/expressions/asOperator/asOperatorASI.ts b/tests/cases/conformance/expressions/asOperator/asOperatorASI.ts new file mode 100644 index 0000000000000..a4dd44a15add1 --- /dev/null +++ b/tests/cases/conformance/expressions/asOperator/asOperatorASI.ts @@ -0,0 +1,10 @@ +class Foo { } +declare function as(...args: any[]); + +// Example 1 +var x = 10 +as `Hello world`; // should not error + +// Example 2 +var y = 20 +as(Foo); // should emit From c1e02c41deba5eb60b70fa89c2dd6e200c625aa1 Mon Sep 17 00:00:00 2001 From: Ryan Cavanaugh Date: Tue, 19 May 2015 18:12:52 -0700 Subject: [PATCH 09/12] Add test for things named 'as' as suggested --- tests/baselines/reference/asOperatorNames.errors.txt | 11 +++++++++++ tests/baselines/reference/asOperatorNames.js | 12 ++++++++++++ .../expressions/asOperator/asOperatorNames.ts | 4 ++++ 3 files changed, 27 insertions(+) create mode 100644 tests/baselines/reference/asOperatorNames.errors.txt create mode 100644 tests/baselines/reference/asOperatorNames.js create mode 100644 tests/cases/conformance/expressions/asOperator/asOperatorNames.ts diff --git a/tests/baselines/reference/asOperatorNames.errors.txt b/tests/baselines/reference/asOperatorNames.errors.txt new file mode 100644 index 0000000000000..e3dfaab98845b --- /dev/null +++ b/tests/baselines/reference/asOperatorNames.errors.txt @@ -0,0 +1,11 @@ +tests/cases/conformance/expressions/asOperator/asOperatorNames.ts(2,9): error TS2352: Neither type 'number' nor type 'string' is assignable to the other. + + +==== tests/cases/conformance/expressions/asOperator/asOperatorNames.ts (1 errors) ==== + var a = 20; + var b = a as string; + ~~~~~~~~~~~ +!!! error TS2352: Neither type 'number' nor type 'string' is assignable to the other. + var as = "hello"; + var as1 = as as string; + \ No newline at end of file diff --git a/tests/baselines/reference/asOperatorNames.js b/tests/baselines/reference/asOperatorNames.js new file mode 100644 index 0000000000000..35e80d080e334 --- /dev/null +++ b/tests/baselines/reference/asOperatorNames.js @@ -0,0 +1,12 @@ +//// [asOperatorNames.ts] +var a = 20; +var b = a as string; +var as = "hello"; +var as1 = as as string; + + +//// [asOperatorNames.js] +var a = 20; +var b = a; +var as = "hello"; +var as1 = as; diff --git a/tests/cases/conformance/expressions/asOperator/asOperatorNames.ts b/tests/cases/conformance/expressions/asOperator/asOperatorNames.ts new file mode 100644 index 0000000000000..a0b54d43e8451 --- /dev/null +++ b/tests/cases/conformance/expressions/asOperator/asOperatorNames.ts @@ -0,0 +1,4 @@ +var a = 20; +var b = a as string; +var as = "hello"; +var as1 = as as string; From d127775d830cfce3df2879cc38b73f1bb6eb84bf Mon Sep 17 00:00:00 2001 From: Ryan Cavanaugh Date: Wed, 20 May 2015 11:59:38 -0700 Subject: [PATCH 10/12] CR feedback --- src/compiler/parser.ts | 6 +++++- src/compiler/types.ts | 1 - 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 3fe334ab1dbe7..4c3e3406bb4ce 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -2822,10 +2822,14 @@ module ts { } if (token === SyntaxKind.AsKeyword) { + // Make sure we *do* perform ASI for constructs like this: + // var x = foo + // as (Bar) + // This should be parsed as an initialized variable, followed by a function call to 'as' with the argument 'Bar' if (canParseSemicolon()) { break; } else { - parseTokenNode(); + nextToken(); leftOperand = makeAsExpression(leftOperand, parseType()); } } else { diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 84006a2d89596..66a25a849e4e9 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -674,7 +674,6 @@ module ts { export interface AsExpression extends Expression { expression: Expression; - asToken: Node; type: TypeNode; } From 9e6e2654c3a80b436bc1436d6da1e06324b92cfd Mon Sep 17 00:00:00 2001 From: Ryan Cavanaugh Date: Wed, 20 May 2015 12:30:00 -0700 Subject: [PATCH 11/12] Whitespace --- src/compiler/parser.ts | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 4c3e3406bb4ce..a53f3fcd8157f 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -2823,16 +2823,19 @@ module ts { if (token === SyntaxKind.AsKeyword) { // Make sure we *do* perform ASI for constructs like this: - // var x = foo - // as (Bar) - // This should be parsed as an initialized variable, followed by a function call to 'as' with the argument 'Bar' + // var x = foo + // as (Bar) + // This should be parsed as an initialized variable, followed + // by a function call to 'as' with the argument 'Bar' if (canParseSemicolon()) { break; - } else { + } + else { nextToken(); leftOperand = makeAsExpression(leftOperand, parseType()); } - } else { + } + else { leftOperand = makeBinaryExpression(leftOperand, parseTokenNode(), parseBinaryExpressionOrHigher(newPrecedence)); } } From 225e695d62007909bad1c2e8ead03e66385dfeb5 Mon Sep 17 00:00:00 2001 From: Ryan Cavanaugh Date: Wed, 20 May 2015 14:03:57 -0700 Subject: [PATCH 12/12] Add contextual typing for 'as' and clean up a bunch of missed 'switch' cases --- src/compiler/checker.ts | 8 ++++++-- src/compiler/utilities.ts | 4 +++- tests/baselines/reference/asOperator1.symbols | 2 ++ tests/baselines/reference/asOperator1.types | 8 ++++++-- tests/baselines/reference/asOperator3.js | 2 +- tests/baselines/reference/asOperator3.types | 8 ++++++++ .../reference/asOperatorContextualType.errors.txt | 10 ++++++++++ tests/baselines/reference/asOperatorContextualType.js | 7 +++++++ .../expressions/asOperator/asOperatorContextualType.ts | 2 ++ 9 files changed, 45 insertions(+), 6 deletions(-) create mode 100644 tests/baselines/reference/asOperatorContextualType.errors.txt create mode 100644 tests/baselines/reference/asOperatorContextualType.js create mode 100644 tests/cases/conformance/expressions/asOperator/asOperatorContextualType.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 98d8df6a6168f..07e64d700a61b 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -5192,6 +5192,7 @@ module ts { case SyntaxKind.CallExpression: case SyntaxKind.NewExpression: case SyntaxKind.TypeAssertionExpression: + case SyntaxKind.AsExpression: case SyntaxKind.ParenthesizedExpression: case SyntaxKind.PrefixUnaryExpression: case SyntaxKind.DeleteExpression: @@ -5958,7 +5959,8 @@ module ts { case SyntaxKind.NewExpression: return getContextualTypeForArgument(parent, node); case SyntaxKind.TypeAssertionExpression: - return getTypeFromTypeNode((parent).type); + case SyntaxKind.AsExpression: + return getTypeFromTypeNode((parent).type); case SyntaxKind.BinaryExpression: return getContextualTypeForBinaryOperand(node); case SyntaxKind.PropertyAssignment: @@ -10946,6 +10948,7 @@ module ts { case SyntaxKind.TemplateExpression: case SyntaxKind.TemplateSpan: case SyntaxKind.TypeAssertionExpression: + case SyntaxKind.AsExpression: case SyntaxKind.ParenthesizedExpression: case SyntaxKind.TypeOfExpression: case SyntaxKind.VoidExpression: @@ -11287,7 +11290,8 @@ module ts { case SyntaxKind.IndexSignature: return node === (parent).type; case SyntaxKind.TypeAssertionExpression: - return node === (parent).type; + case SyntaxKind.AsExpression: + return node === (parent).type; case SyntaxKind.CallExpression: case SyntaxKind.NewExpression: return (parent).typeArguments && indexOf((parent).typeArguments, node) >= 0; diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 356337e1315cb..14f5173da58d4 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -717,6 +717,7 @@ module ts { case SyntaxKind.CallExpression: case SyntaxKind.NewExpression: case SyntaxKind.TaggedTemplateExpression: + case SyntaxKind.AsExpression: case SyntaxKind.TypeAssertionExpression: case SyntaxKind.ParenthesizedExpression: case SyntaxKind.FunctionExpression: @@ -779,7 +780,8 @@ module ts { return (forInStatement.initializer === node && forInStatement.initializer.kind !== SyntaxKind.VariableDeclarationList) || forInStatement.expression === node; case SyntaxKind.TypeAssertionExpression: - return node === (parent).expression; + case SyntaxKind.AsExpression: + return node === (parent).expression; case SyntaxKind.TemplateSpan: return node === (parent).expression; case SyntaxKind.ComputedPropertyName: diff --git a/tests/baselines/reference/asOperator1.symbols b/tests/baselines/reference/asOperator1.symbols index a695fe02b5def..b6455af5919b0 100644 --- a/tests/baselines/reference/asOperator1.symbols +++ b/tests/baselines/reference/asOperator1.symbols @@ -4,6 +4,7 @@ var as = 43; var x = undefined as number; >x : Symbol(x, Decl(asOperator1.ts, 1, 3)) +>undefined : Symbol(undefined) var y = (null as string).length; >y : Symbol(y, Decl(asOperator1.ts, 2, 3)) @@ -12,4 +13,5 @@ var y = (null as string).length; var z = Date as any as string; >z : Symbol(z, Decl(asOperator1.ts, 3, 3)) +>Date : Symbol(Date, Decl(lib.d.ts, 633, 23), Decl(lib.d.ts, 815, 11)) diff --git a/tests/baselines/reference/asOperator1.types b/tests/baselines/reference/asOperator1.types index 49da534b17be2..dae17c581c419 100644 --- a/tests/baselines/reference/asOperator1.types +++ b/tests/baselines/reference/asOperator1.types @@ -5,16 +5,20 @@ var as = 43; var x = undefined as number; >x : number ->undefined : any +>undefined as number : number +>undefined : undefined var y = (null as string).length; >y : number >(null as string).length : number >(null as string) : string +>null as string : string >null : null >length : number var z = Date as any as string; >z : string ->Date : any +>Date as any as string : string +>Date as any : any +>Date : DateConstructor diff --git a/tests/baselines/reference/asOperator3.js b/tests/baselines/reference/asOperator3.js index 42181cd87c4a1..406eae1c9d68b 100644 --- a/tests/baselines/reference/asOperator3.js +++ b/tests/baselines/reference/asOperator3.js @@ -14,7 +14,7 @@ var h = tag `Hello` as string; var a = "" + 123 + 456; var b = "leading " + 123 + 456; var c = 123 + 456 + " trailing"; -var d = "Hello " + 123 + " World"; +var d = ("Hello " + 123 + " World"); var e = "Hello"; var f = 1 + (1 + " end of string"); var g = (_a = ["Hello ", " World"], _a.raw = ["Hello ", " World"], tag(_a, 123)); diff --git a/tests/baselines/reference/asOperator3.types b/tests/baselines/reference/asOperator3.types index 1b3e1c42d1242..507dfd8b5726f 100644 --- a/tests/baselines/reference/asOperator3.types +++ b/tests/baselines/reference/asOperator3.types @@ -6,6 +6,7 @@ declare function tag(...x: any[]): any; var a = `${123 + 456 as number}`; >a : string >`${123 + 456 as number}` : string +>123 + 456 as number : number >123 + 456 : number >123 : number >456 : number @@ -13,6 +14,7 @@ var a = `${123 + 456 as number}`; var b = `leading ${123 + 456 as number}`; >b : string >`leading ${123 + 456 as number}` : string +>123 + 456 as number : number >123 + 456 : number >123 : number >456 : number @@ -20,21 +22,25 @@ var b = `leading ${123 + 456 as number}`; var c = `${123 + 456 as number} trailing`; >c : string >`${123 + 456 as number} trailing` : string +>123 + 456 as number : number >123 + 456 : number >123 : number >456 : number var d = `Hello ${123} World` as string; >d : string +>`Hello ${123} World` as string : string >`Hello ${123} World` : string >123 : number var e = `Hello` as string; >e : string +>`Hello` as string : string >`Hello` : string var f = 1 + `${1} end of string` as string; >f : string +>1 + `${1} end of string` as string : string >1 + `${1} end of string` : string >1 : number >`${1} end of string` : string @@ -42,6 +48,7 @@ var f = 1 + `${1} end of string` as string; var g = tag `Hello ${123} World` as string; >g : string +>tag `Hello ${123} World` as string : string >tag `Hello ${123} World` : any >tag : (...x: any[]) => any >`Hello ${123} World` : string @@ -49,6 +56,7 @@ var g = tag `Hello ${123} World` as string; var h = tag `Hello` as string; >h : string +>tag `Hello` as string : string >tag `Hello` : any >tag : (...x: any[]) => any >`Hello` : string diff --git a/tests/baselines/reference/asOperatorContextualType.errors.txt b/tests/baselines/reference/asOperatorContextualType.errors.txt new file mode 100644 index 0000000000000..c53b407b5cf02 --- /dev/null +++ b/tests/baselines/reference/asOperatorContextualType.errors.txt @@ -0,0 +1,10 @@ +tests/cases/conformance/expressions/asOperator/asOperatorContextualType.ts(2,9): error TS2352: Neither type '(v: number) => number' nor type '(x: number) => string' is assignable to the other. + Type 'number' is not assignable to type 'string'. + + +==== tests/cases/conformance/expressions/asOperator/asOperatorContextualType.ts (1 errors) ==== + // should error + var x = (v => v) as (x: number) => string; + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2352: Neither type '(v: number) => number' nor type '(x: number) => string' is assignable to the other. +!!! error TS2352: Type 'number' is not assignable to type 'string'. \ No newline at end of file diff --git a/tests/baselines/reference/asOperatorContextualType.js b/tests/baselines/reference/asOperatorContextualType.js new file mode 100644 index 0000000000000..7b495ada8f403 --- /dev/null +++ b/tests/baselines/reference/asOperatorContextualType.js @@ -0,0 +1,7 @@ +//// [asOperatorContextualType.ts] +// should error +var x = (v => v) as (x: number) => string; + +//// [asOperatorContextualType.js] +// should error +var x = (function (v) { return v; }); diff --git a/tests/cases/conformance/expressions/asOperator/asOperatorContextualType.ts b/tests/cases/conformance/expressions/asOperator/asOperatorContextualType.ts new file mode 100644 index 0000000000000..d3a23e224ba3d --- /dev/null +++ b/tests/cases/conformance/expressions/asOperator/asOperatorContextualType.ts @@ -0,0 +1,2 @@ +// should error +var x = (v => v) as (x: number) => string; \ No newline at end of file