diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 5d26a30c3b7dd..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: @@ -7261,7 +7263,7 @@ module ts { return getReturnTypeOfSignature(getResolvedSignature(node)); } - function checkTypeAssertion(node: TypeAssertion): Type { + function checkAssertion(node: AssertionExpression) { let exprType = checkExpression(node.expression); let targetType = getTypeFromTypeNode(node.type); if (produceDiagnostics && targetType !== unknownType) { @@ -8134,8 +8136,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: @@ -8145,6 +8145,9 @@ module ts { return checkFunctionExpressionOrObjectLiteralMethod(node, contextualMapper); case SyntaxKind.TypeOfExpression: return checkTypeOfExpression(node); + case SyntaxKind.TypeAssertionExpression: + case SyntaxKind.AsExpression: + return checkAssertion(node); case SyntaxKind.DeleteExpression: return checkDeleteExpression(node); case SyntaxKind.VoidExpression: @@ -10945,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: @@ -11286,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/emitter.ts b/src/compiler/emitter.ts index c9d23ec5ceebf..42e8ec7a45e91 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -1790,8 +1790,8 @@ var __param = (this && this.__param) || function (paramIndex, decorator) { } function skipParentheses(node: Expression): Expression { - while (node.kind === SyntaxKind.ParenthesizedExpression || node.kind === SyntaxKind.TypeAssertionExpression) { - node = (node).expression; + while (node.kind === SyntaxKind.ParenthesizedExpression || node.kind === SyntaxKind.TypeAssertionExpression || node.kind === SyntaxKind.AsExpression) { + 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) @@ -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).expression); case SyntaxKind.ParenthesizedExpression: return emitParenExpression(node); case SyntaxKind.FunctionDeclaration: diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index af9b486a1da4f..a53f3fcd8157f 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -159,6 +159,9 @@ module ts { return visitNode(cbNode, (node).left) || visitNode(cbNode, (node).operatorToken) || visitNode(cbNode, (node).right); + case SyntaxKind.AsExpression: + return visitNode(cbNode, (node).expression) || + visitNode(cbNode, (node).type); case SyntaxKind.ConditionalExpression: return visitNode(cbNode, (node).condition) || visitNode(cbNode, (node).questionToken) || @@ -2818,7 +2821,23 @@ module ts { break; } - leftOperand = makeBinaryExpression(leftOperand, parseTokenNode(), parseBinaryExpressionOrHigher(newPrecedence)); + 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 { + nextToken(); + leftOperand = makeAsExpression(leftOperand, parseType()); + } + } + else { + leftOperand = makeBinaryExpression(leftOperand, parseTokenNode(), parseBinaryExpressionOrHigher(newPrecedence)); + } } return leftOperand; @@ -2855,6 +2874,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 +2902,13 @@ module ts { return finishNode(node); } + function makeAsExpression(left: Expression, right: TypeNode): AsExpression { + let node = createNode(SyntaxKind.AsExpression, left.pos); + node.expression = left; + node.type = 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..66a25a849e4e9 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -207,6 +207,7 @@ module ts { ClassExpression, OmittedExpression, ExpressionWithTypeArguments, + AsExpression, // Misc TemplateSpan, SemicolonClassElement, @@ -404,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; @@ -669,6 +672,11 @@ module ts { right: Expression; } + export interface AsExpression extends Expression { + expression: Expression; + type: TypeNode; + } + export interface ConditionalExpression extends Expression { condition: Expression; questionToken: Node; 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/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/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..a00d31d31ef97 --- /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 = undefined; +var y = null.length; +var z = Date; diff --git a/tests/baselines/reference/asOperator1.symbols b/tests/baselines/reference/asOperator1.symbols new file mode 100644 index 0000000000000..b6455af5919b0 --- /dev/null +++ b/tests/baselines/reference/asOperator1.symbols @@ -0,0 +1,17 @@ +=== 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)) +>undefined : Symbol(undefined) + +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)) +>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 new file mode 100644 index 0000000000000..dae17c581c419 --- /dev/null +++ b/tests/baselines/reference/asOperator1.types @@ -0,0 +1,24 @@ +=== tests/cases/conformance/expressions/asOperator/asOperator1.ts === +var as = 43; +>as : number +>43 : number + +var x = undefined as number; +>x : number +>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 as any as string : string +>Date as any : any +>Date : DateConstructor + 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/baselines/reference/asOperator3.js b/tests/baselines/reference/asOperator3.js new file mode 100644 index 0000000000000..406eae1c9d68b --- /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..507dfd8b5726f --- /dev/null +++ b/tests/baselines/reference/asOperator3.types @@ -0,0 +1,63 @@ +=== 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 as number : number +>123 + 456 : number +>123 : number +>456 : 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 + +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 +>1 : number + +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 +>123 : number + +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/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/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/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/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; 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; 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 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 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 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; 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;");