diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 228b1067bb0..d4ce6655a21 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -7313,15 +7313,15 @@ namespace ts { } function checkObjectLiteral(node: ObjectLiteralExpression, contextualMapper?: TypeMapper): Type { + let inDestructuringPattern = isAssignmentTarget(node); // Grammar checking - checkGrammarObjectLiteralExpression(node); + checkGrammarObjectLiteralExpression(node, inDestructuringPattern); let propertiesTable: SymbolTable = {}; let propertiesArray: Symbol[] = []; let contextualType = getContextualType(node); let contextualTypeHasPattern = contextualType && contextualType.pattern && (contextualType.pattern.kind === SyntaxKind.ObjectBindingPattern || contextualType.pattern.kind === SyntaxKind.ObjectLiteralExpression); - let inDestructuringPattern = isAssignmentTarget(node); let typeFlags: TypeFlags = 0; for (let memberDecl of node.properties) { @@ -7345,7 +7345,10 @@ namespace ts { if (inDestructuringPattern) { // If object literal is an assignment pattern and if the assignment pattern specifies a default value // for the property, make the property optional. - if (memberDecl.kind === SyntaxKind.PropertyAssignment && hasDefaultValue((memberDecl).initializer)) { + const isOptional = + (memberDecl.kind === SyntaxKind.PropertyAssignment && hasDefaultValue((memberDecl).initializer)) || + (memberDecl.kind === SyntaxKind.ShorthandPropertyAssignment && (memberDecl).objectAssignmentInitializer); + if (isOptional) { prop.flags |= SymbolFlags.Optional; } } @@ -9909,32 +9912,32 @@ namespace ts { return (symbol.flags & SymbolFlags.ConstEnum) !== 0; } - function checkInstanceOfExpression(node: BinaryExpression, leftType: Type, rightType: Type): Type { + function checkInstanceOfExpression(left: Expression, right: Expression, leftType: Type, rightType: Type): Type { // TypeScript 1.0 spec (April 2014): 4.15.4 // The instanceof operator requires the left operand to be of type Any, an object type, or a type parameter type, // and the right operand to be of type Any or a subtype of the 'Function' interface type. // The result is always of the Boolean primitive type. // NOTE: do not raise error if leftType is unknown as related error was already reported if (allConstituentTypesHaveKind(leftType, TypeFlags.Primitive)) { - error(node.left, Diagnostics.The_left_hand_side_of_an_instanceof_expression_must_be_of_type_any_an_object_type_or_a_type_parameter); + error(left, Diagnostics.The_left_hand_side_of_an_instanceof_expression_must_be_of_type_any_an_object_type_or_a_type_parameter); } // NOTE: do not raise error if right is unknown as related error was already reported if (!(isTypeAny(rightType) || isTypeSubtypeOf(rightType, globalFunctionType))) { - error(node.right, Diagnostics.The_right_hand_side_of_an_instanceof_expression_must_be_of_type_any_or_of_a_type_assignable_to_the_Function_interface_type); + error(right, Diagnostics.The_right_hand_side_of_an_instanceof_expression_must_be_of_type_any_or_of_a_type_assignable_to_the_Function_interface_type); } return booleanType; } - function checkInExpression(node: BinaryExpression, leftType: Type, rightType: Type): Type { + function checkInExpression(left: Expression, right: Expression, leftType: Type, rightType: Type): Type { // TypeScript 1.0 spec (April 2014): 4.15.5 // The in operator requires the left operand to be of type Any, the String primitive type, or the Number primitive type, // and the right operand to be of type Any, an object type, or a type parameter type. // The result is always of the Boolean primitive type. if (!isTypeAnyOrAllConstituentTypesHaveKind(leftType, TypeFlags.StringLike | TypeFlags.NumberLike | TypeFlags.ESSymbol)) { - error(node.left, Diagnostics.The_left_hand_side_of_an_in_expression_must_be_of_type_any_string_number_or_symbol); + error(left, Diagnostics.The_left_hand_side_of_an_in_expression_must_be_of_type_any_string_number_or_symbol); } if (!isTypeAnyOrAllConstituentTypesHaveKind(rightType, TypeFlags.ObjectType | TypeFlags.TypeParameter)) { - error(node.right, Diagnostics.The_right_hand_side_of_an_in_expression_must_be_of_type_any_an_object_type_or_a_type_parameter); + error(right, Diagnostics.The_right_hand_side_of_an_in_expression_must_be_of_type_any_an_object_type_or_a_type_parameter); } return booleanType; } @@ -9951,7 +9954,12 @@ namespace ts { isNumericLiteralName(name.text) && getIndexTypeOfType(sourceType, IndexKind.Number) || getIndexTypeOfType(sourceType, IndexKind.String); if (type) { - checkDestructuringAssignment((p).initializer || name, type); + if (p.kind === SyntaxKind.ShorthandPropertyAssignment) { + checkDestructuringAssignment(p, type); + } + else { + checkDestructuringAssignment((p).initializer || name, type); + } } else { error(name, Diagnostics.Type_0_has_no_property_1_and_no_string_index_signature, typeToString(sourceType), declarationNameToString(name)); @@ -10011,7 +10019,19 @@ namespace ts { return sourceType; } - function checkDestructuringAssignment(target: Expression, sourceType: Type, contextualMapper?: TypeMapper): Type { + function checkDestructuringAssignment(exprOrAssignment: Expression | ShorthandPropertyAssignment, sourceType: Type, contextualMapper?: TypeMapper): Type { + let target: Expression; + if (exprOrAssignment.kind === SyntaxKind.ShorthandPropertyAssignment) { + const prop = exprOrAssignment; + if (prop.objectAssignmentInitializer) { + checkBinaryLikeExpression(prop.name, prop.equalsToken, prop.objectAssignmentInitializer, contextualMapper); + } + target = (exprOrAssignment).name; + } + else { + target = exprOrAssignment; + } + if (target.kind === SyntaxKind.BinaryExpression && (target).operatorToken.kind === SyntaxKind.EqualsToken) { checkBinaryExpression(target, contextualMapper); target = (target).left; @@ -10034,12 +10054,16 @@ namespace ts { } function checkBinaryExpression(node: BinaryExpression, contextualMapper?: TypeMapper) { - let operator = node.operatorToken.kind; - if (operator === SyntaxKind.EqualsToken && (node.left.kind === SyntaxKind.ObjectLiteralExpression || node.left.kind === SyntaxKind.ArrayLiteralExpression)) { - return checkDestructuringAssignment(node.left, checkExpression(node.right, contextualMapper), contextualMapper); + return checkBinaryLikeExpression(node.left, node.operatorToken, node.right, contextualMapper, node); + } + + function checkBinaryLikeExpression(left: Expression, operatorToken: Node, right: Expression, contextualMapper?: TypeMapper, errorNode?: Node) { + let operator = operatorToken.kind; + if (operator === SyntaxKind.EqualsToken && (left.kind === SyntaxKind.ObjectLiteralExpression || left.kind === SyntaxKind.ArrayLiteralExpression)) { + return checkDestructuringAssignment(left, checkExpression(right, contextualMapper), contextualMapper); } - let leftType = checkExpression(node.left, contextualMapper); - let rightType = checkExpression(node.right, contextualMapper); + let leftType = checkExpression(left, contextualMapper); + let rightType = checkExpression(right, contextualMapper); switch (operator) { case SyntaxKind.AsteriskToken: case SyntaxKind.AsteriskEqualsToken: @@ -10075,13 +10099,13 @@ namespace ts { // try and return them a helpful suggestion if ((leftType.flags & TypeFlags.Boolean) && (rightType.flags & TypeFlags.Boolean) && - (suggestedOperator = getSuggestedBooleanOperator(node.operatorToken.kind)) !== undefined) { - error(node, Diagnostics.The_0_operator_is_not_allowed_for_boolean_types_Consider_using_1_instead, tokenToString(node.operatorToken.kind), tokenToString(suggestedOperator)); + (suggestedOperator = getSuggestedBooleanOperator(operatorToken.kind)) !== undefined) { + error(errorNode || operatorToken, Diagnostics.The_0_operator_is_not_allowed_for_boolean_types_Consider_using_1_instead, tokenToString(operatorToken.kind), tokenToString(suggestedOperator)); } else { // otherwise just check each operand separately and report errors as normal - let leftOk = checkArithmeticOperandType(node.left, leftType, Diagnostics.The_left_hand_side_of_an_arithmetic_operation_must_be_of_type_any_number_or_an_enum_type); - let rightOk = checkArithmeticOperandType(node.right, rightType, Diagnostics.The_right_hand_side_of_an_arithmetic_operation_must_be_of_type_any_number_or_an_enum_type); + let leftOk = checkArithmeticOperandType(left, leftType, Diagnostics.The_left_hand_side_of_an_arithmetic_operation_must_be_of_type_any_number_or_an_enum_type); + let rightOk = checkArithmeticOperandType(right, rightType, Diagnostics.The_right_hand_side_of_an_arithmetic_operation_must_be_of_type_any_number_or_an_enum_type); if (leftOk && rightOk) { checkAssignmentOperator(numberType); } @@ -10147,9 +10171,9 @@ namespace ts { } return booleanType; case SyntaxKind.InstanceOfKeyword: - return checkInstanceOfExpression(node, leftType, rightType); + return checkInstanceOfExpression(left, right, leftType, rightType); case SyntaxKind.InKeyword: - return checkInExpression(node, leftType, rightType); + return checkInExpression(left, right, leftType, rightType); case SyntaxKind.AmpersandAmpersandToken: return rightType; case SyntaxKind.BarBarToken: @@ -10164,8 +10188,8 @@ namespace ts { // Return true if there was no error, false if there was an error. function checkForDisallowedESSymbolOperand(operator: SyntaxKind): boolean { let offendingSymbolOperand = - someConstituentTypeHasKind(leftType, TypeFlags.ESSymbol) ? node.left : - someConstituentTypeHasKind(rightType, TypeFlags.ESSymbol) ? node.right : + someConstituentTypeHasKind(leftType, TypeFlags.ESSymbol) ? left : + someConstituentTypeHasKind(rightType, TypeFlags.ESSymbol) ? right : undefined; if (offendingSymbolOperand) { error(offendingSymbolOperand, Diagnostics.The_0_operator_cannot_be_applied_to_type_symbol, tokenToString(operator)); @@ -10199,17 +10223,17 @@ namespace ts { // requires VarExpr to be classified as a reference // A compound assignment furthermore requires VarExpr to be classified as a reference (section 4.1) // and the type of the non - compound operation to be assignable to the type of VarExpr. - let ok = checkReferenceExpression(node.left, Diagnostics.Invalid_left_hand_side_of_assignment_expression, Diagnostics.Left_hand_side_of_assignment_expression_cannot_be_a_constant); + let ok = checkReferenceExpression(left, Diagnostics.Invalid_left_hand_side_of_assignment_expression, Diagnostics.Left_hand_side_of_assignment_expression_cannot_be_a_constant); // Use default messages if (ok) { // to avoid cascading errors check assignability only if 'isReference' check succeeded and no errors were reported - checkTypeAssignableTo(valueType, leftType, node.left, /*headMessage*/ undefined); + checkTypeAssignableTo(valueType, leftType, left, /*headMessage*/ undefined); } } } function reportOperatorError() { - error(node, Diagnostics.Operator_0_cannot_be_applied_to_types_1_and_2, tokenToString(node.operatorToken.kind), typeToString(leftType), typeToString(rightType)); + error(errorNode || operatorToken, Diagnostics.Operator_0_cannot_be_applied_to_types_1_and_2, tokenToString(operatorToken.kind), typeToString(leftType), typeToString(rightType)); } } @@ -15421,7 +15445,7 @@ namespace ts { } } - function checkGrammarObjectLiteralExpression(node: ObjectLiteralExpression) { + function checkGrammarObjectLiteralExpression(node: ObjectLiteralExpression, inDestructuring: boolean) { let seen: Map = {}; let Property = 1; let GetAccessor = 2; @@ -15437,6 +15461,12 @@ namespace ts { continue; } + if (prop.kind === SyntaxKind.ShorthandPropertyAssignment && !inDestructuring && (prop).objectAssignmentInitializer) { + // having objectAssignmentInitializer is only valid in ObjectAssignmentPattern + // outside of destructuring it is a syntax error + return grammarErrorOnNode((prop).equalsToken, Diagnostics.can_only_be_used_in_an_object_literal_property_inside_a_destructuring_assignment); + } + // ECMA-262 11.1.5 Object Initialiser // If previous is not undefined then throw a SyntaxError exception if any of the following conditions are true // a.This production is contained in strict code and IsDataDescriptor(previous) is true and diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 22b65b58111..b391545a733 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -800,6 +800,10 @@ "category": "Error", "code": 1311 }, + "'=' can only be used in an object literal property inside a destructuring assignment.": { + "category": "Error", + "code": 1312 + }, "Duplicate identifier '{0}'.": { "category": "Error", "code": 2300 diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index c998415a292..f01b7cb54a4 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -2311,6 +2311,11 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi write(": "); emit(node.name); } + + if (languageVersion >= ScriptTarget.ES6 && node.objectAssignmentInitializer) { + write(" = "); + emit(node.objectAssignmentInitializer); + } } function tryEmitConstantValue(node: PropertyAccessExpression | ElementAccessExpression): boolean { @@ -3574,7 +3579,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi for (let p of properties) { if (p.kind === SyntaxKind.PropertyAssignment || p.kind === SyntaxKind.ShorthandPropertyAssignment) { let propName = (p).name; - emitDestructuringAssignment((p).initializer || propName, createPropertyAccessForDestructuringProperty(value, propName)); + let target = p.kind === SyntaxKind.ShorthandPropertyAssignment ? p : (p).initializer || propName; + emitDestructuringAssignment(target, createPropertyAccessForDestructuringProperty(value, propName)); } } } @@ -3599,8 +3605,14 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi } } - function emitDestructuringAssignment(target: Expression, value: Expression) { - if (target.kind === SyntaxKind.BinaryExpression && (target).operatorToken.kind === SyntaxKind.EqualsToken) { + function emitDestructuringAssignment(target: Expression | ShorthandPropertyAssignment, value: Expression) { + if (target.kind === SyntaxKind.ShorthandPropertyAssignment) { + if ((target).objectAssignmentInitializer) { + value = createDefaultValueCheck(value, (target).objectAssignmentInitializer); + } + target = (target).name; + } + else if (target.kind === SyntaxKind.BinaryExpression && (target).operatorToken.kind === SyntaxKind.EqualsToken) { value = createDefaultValueCheck(value, (target).right); target = (target).left; } diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index dcdaec98318..09fa2ba3b82 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -57,11 +57,17 @@ namespace ts { return visitNode(cbNode, (node).name) || visitNode(cbNode, (node).constraint) || visitNode(cbNode, (node).expression); + case SyntaxKind.ShorthandPropertyAssignment: + return visitNodes(cbNodes, node.decorators) || + visitNodes(cbNodes, node.modifiers) || + visitNode(cbNode, (node).name) || + visitNode(cbNode, (node).questionToken) || + visitNode(cbNode, (node).equalsToken) || + visitNode(cbNode, (node).objectAssignmentInitializer); case SyntaxKind.Parameter: case SyntaxKind.PropertyDeclaration: case SyntaxKind.PropertySignature: case SyntaxKind.PropertyAssignment: - case SyntaxKind.ShorthandPropertyAssignment: case SyntaxKind.VariableDeclaration: case SyntaxKind.BindingElement: return visitNodes(cbNodes, node.decorators) || @@ -3758,11 +3764,23 @@ namespace ts { return parseMethodDeclaration(fullStart, decorators, modifiers, asteriskToken, propertyName, questionToken); } - // Parse to check if it is short-hand property assignment or normal property assignment - if ((token === SyntaxKind.CommaToken || token === SyntaxKind.CloseBraceToken) && tokenIsIdentifier) { + // check if it is short-hand property assignment or normal property assignment + // NOTE: if token is EqualsToken it is interpreted as CoverInitializedName production + // CoverInitializedName[Yield] : + // IdentifierReference[?Yield] Initializer[In, ?Yield] + // this is necessary because ObjectLiteral productions are also used to cover grammar for ObjectAssignmentPattern + const isShorthandPropertyAssignment = + tokenIsIdentifier && (token === SyntaxKind.CommaToken || token === SyntaxKind.CloseBraceToken || token === SyntaxKind.EqualsToken); + + if (isShorthandPropertyAssignment) { let shorthandDeclaration = createNode(SyntaxKind.ShorthandPropertyAssignment, fullStart); shorthandDeclaration.name = propertyName; shorthandDeclaration.questionToken = questionToken; + const equalsToken = parseOptionalToken(SyntaxKind.EqualsToken); + if (equalsToken) { + shorthandDeclaration.equalsToken = equalsToken; + shorthandDeclaration.objectAssignmentInitializer = allowInAnd(parseAssignmentExpressionOrHigher); + } return finishNode(shorthandDeclaration); } else { diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 773083d49b6..cbaa3e65e27 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -562,6 +562,10 @@ namespace ts { export interface ShorthandPropertyAssignment extends ObjectLiteralElement { name: Identifier; questionToken?: Node; + // used when ObjectLiteralExpression is used in ObjectAssignmentPattern + // it is grammar error to appear in actual object initializer + equalsToken?: Node; + objectAssignmentInitializer?: Expression; } // SyntaxKind.VariableDeclaration diff --git a/tests/baselines/reference/for-of48.errors.txt b/tests/baselines/reference/for-of48.errors.txt index f6826e14c61..8a8fd668714 100644 --- a/tests/baselines/reference/for-of48.errors.txt +++ b/tests/baselines/reference/for-of48.errors.txt @@ -1,4 +1,4 @@ -tests/cases/conformance/es6/for-ofStatements/for-of48.ts(4,12): error TS1005: ':' expected. +tests/cases/conformance/es6/for-ofStatements/for-of48.ts(4,10): error TS2322: Type 'boolean' is not assignable to type 'number'. ==== tests/cases/conformance/es6/for-ofStatements/for-of48.ts (1 errors) ==== @@ -6,8 +6,8 @@ tests/cases/conformance/es6/for-ofStatements/for-of48.ts(4,12): error TS1005: ': var array = [{ x: "", y: true }] enum E { x } for ({x, y = E.x} of array) { - ~ -!!! error TS1005: ':' expected. + ~ +!!! error TS2322: Type 'boolean' is not assignable to type 'number'. x; y; } \ No newline at end of file diff --git a/tests/baselines/reference/for-of48.js b/tests/baselines/reference/for-of48.js index 2a5e4e32b94..65e23076fd9 100644 --- a/tests/baselines/reference/for-of48.js +++ b/tests/baselines/reference/for-of48.js @@ -14,7 +14,7 @@ var E; (function (E) { E[E["x"] = 0] = "x"; })(E || (E = {})); -for ({ x, y: = E.x } of array) { +for ({ x, y = E.x } of array) { x; y; } diff --git a/tests/baselines/reference/shorthandPropertyAssignmentsInDestructuring.errors.txt b/tests/baselines/reference/shorthandPropertyAssignmentsInDestructuring.errors.txt new file mode 100644 index 00000000000..7ac5fe9a26c --- /dev/null +++ b/tests/baselines/reference/shorthandPropertyAssignmentsInDestructuring.errors.txt @@ -0,0 +1,164 @@ +tests/cases/compiler/shorthandPropertyAssignmentsInDestructuring.ts(16,9): error TS2459: Type '{}' has no property 's1' and no string index signature. +tests/cases/compiler/shorthandPropertyAssignmentsInDestructuring.ts(22,9): error TS2459: Type '{}' has no property 's1' and no string index signature. +tests/cases/compiler/shorthandPropertyAssignmentsInDestructuring.ts(40,9): error TS2322: Type 'number' is not assignable to type 'string'. +tests/cases/compiler/shorthandPropertyAssignmentsInDestructuring.ts(46,12): error TS2322: Type 'number' is not assignable to type 'string'. +tests/cases/compiler/shorthandPropertyAssignmentsInDestructuring.ts(72,5): error TS2322: Type 'number' is not assignable to type 'string'. +tests/cases/compiler/shorthandPropertyAssignmentsInDestructuring.ts(77,8): error TS2322: Type 'number' is not assignable to type 'string'. +tests/cases/compiler/shorthandPropertyAssignmentsInDestructuring.ts(82,5): error TS2322: Type 'number' is not assignable to type 'string'. +tests/cases/compiler/shorthandPropertyAssignmentsInDestructuring.ts(82,13): error TS2322: Type '{ x: number; }' is not assignable to type '{ x: string; }'. + Types of property 'x' are incompatible. + Type 'number' is not assignable to type 'string'. +tests/cases/compiler/shorthandPropertyAssignmentsInDestructuring.ts(87,8): error TS2322: Type 'number' is not assignable to type 'string'. +tests/cases/compiler/shorthandPropertyAssignmentsInDestructuring.ts(87,19): error TS2322: Type '{ x: number; }' is not assignable to type '{ x: string; }'. + Types of property 'x' are incompatible. + Type 'number' is not assignable to type 'string'. +tests/cases/compiler/shorthandPropertyAssignmentsInDestructuring.ts(113,12): error TS2304: Cannot find name 's'. +tests/cases/compiler/shorthandPropertyAssignmentsInDestructuring.ts(113,14): error TS1312: '=' can only be used in an object literal property inside a destructuring assignment. + + +==== tests/cases/compiler/shorthandPropertyAssignmentsInDestructuring.ts (12 errors) ==== + + + (function() { + var s0; + for ({ s0 = 5 } of [{ s0: 1 }]) { + } + }); + (function() { + var s0; + for ({ s0:s0 = 5 } of [{ s0: 1 }]) { + } + }); + + (function() { + var s1; + for ({ s1 = 5 } of [{}]) { + ~~ +!!! error TS2459: Type '{}' has no property 's1' and no string index signature. + } + }); + + (function() { + var s1; + for ({ s1:s1 = 5 } of [{}]) { + ~~ +!!! error TS2459: Type '{}' has no property 's1' and no string index signature. + } + }); + + (function() { + var s2; + for ({ s2 = 5 } of [{ s2: "" }]) { + } + }); + + (function() { + var s2; + for ({ s2:s2 = 5 } of [{ s2: "" }]) { + } + }); + + (function() { + var s3: string; + for ({ s3 = 5 } of [{ s3: "" }]) { + ~~ +!!! error TS2322: Type 'number' is not assignable to type 'string'. + } + }); + + (function() { + var s3: string; + for ({ s3:s3 = 5 } of [{ s3: "" }]) { + ~~ +!!! error TS2322: Type 'number' is not assignable to type 'string'. + } + }); + + (function() { + let y; + ({ y = 5 } = { y: 1 }) + }); + + (function() { + let y; + ({ y:y = 5 } = { y: 1 }) + }); + + (function() { + let y0: number; + ({ y0 = 5 } = { y0: 1 }) + }); + + (function() { + let y0: number; + ({ y0:y0 = 5 } = { y0: 1 }) + }); + + (function() { + let y1: string; + ({ y1 = 5 } = {}) + ~~ +!!! error TS2322: Type 'number' is not assignable to type 'string'. + }); + + (function() { + let y1: string; + ({ y1:y1 = 5 } = {}) + ~~ +!!! error TS2322: Type 'number' is not assignable to type 'string'. + }); + + (function() { + let y2: string, y3: { x: string }; + ({ y2 = 5, y3 = { x: 1 } } = {}) + ~~ +!!! error TS2322: Type 'number' is not assignable to type 'string'. + ~~ +!!! error TS2322: Type '{ x: number; }' is not assignable to type '{ x: string; }'. +!!! error TS2322: Types of property 'x' are incompatible. +!!! error TS2322: Type 'number' is not assignable to type 'string'. + }); + + (function() { + let y2: string, y3: { x: string }; + ({ y2:y2 = 5, y3:y3 = { x: 1 } } = {}) + ~~ +!!! error TS2322: Type 'number' is not assignable to type 'string'. + ~~ +!!! error TS2322: Type '{ x: number; }' is not assignable to type '{ x: string; }'. +!!! error TS2322: Types of property 'x' are incompatible. +!!! error TS2322: Type 'number' is not assignable to type 'string'. + }); + + (function() { + let y4: number, y5: { x: number }; + ({ y4 = 5, y5 = { x: 1 } } = {}) + }); + + (function() { + let y4: number, y5: { x: number }; + ({ y4:y4 = 5, y5:y5 = { x: 1 } } = {}) + }); + + + (function() { + let z; + ({ z = { x: 5 } } = { z: { x: 1 } }); + }); + + + (function() { + let z; + ({ z:z = { x: 5 } } = { z: { x: 1 } }); + }); + + (function() { + let a = { s = 5 }; + ~ +!!! error TS2304: Cannot find name 's'. + ~ +!!! error TS1312: '=' can only be used in an object literal property inside a destructuring assignment. + }); + + function foo({a = 4, b = { x: 5 }}) { + } \ No newline at end of file diff --git a/tests/baselines/reference/shorthandPropertyAssignmentsInDestructuring.js b/tests/baselines/reference/shorthandPropertyAssignmentsInDestructuring.js new file mode 100644 index 00000000000..981ee08e20c --- /dev/null +++ b/tests/baselines/reference/shorthandPropertyAssignmentsInDestructuring.js @@ -0,0 +1,242 @@ +//// [shorthandPropertyAssignmentsInDestructuring.ts] + + +(function() { + var s0; + for ({ s0 = 5 } of [{ s0: 1 }]) { + } +}); +(function() { + var s0; + for ({ s0:s0 = 5 } of [{ s0: 1 }]) { + } +}); + +(function() { + var s1; + for ({ s1 = 5 } of [{}]) { + } +}); + +(function() { + var s1; + for ({ s1:s1 = 5 } of [{}]) { + } +}); + +(function() { + var s2; + for ({ s2 = 5 } of [{ s2: "" }]) { + } +}); + +(function() { + var s2; + for ({ s2:s2 = 5 } of [{ s2: "" }]) { + } +}); + +(function() { + var s3: string; + for ({ s3 = 5 } of [{ s3: "" }]) { + } +}); + +(function() { + var s3: string; + for ({ s3:s3 = 5 } of [{ s3: "" }]) { + } +}); + +(function() { + let y; + ({ y = 5 } = { y: 1 }) +}); + +(function() { + let y; + ({ y:y = 5 } = { y: 1 }) +}); + +(function() { + let y0: number; + ({ y0 = 5 } = { y0: 1 }) +}); + +(function() { + let y0: number; + ({ y0:y0 = 5 } = { y0: 1 }) +}); + +(function() { + let y1: string; + ({ y1 = 5 } = {}) +}); + +(function() { + let y1: string; + ({ y1:y1 = 5 } = {}) +}); + +(function() { + let y2: string, y3: { x: string }; + ({ y2 = 5, y3 = { x: 1 } } = {}) +}); + +(function() { + let y2: string, y3: { x: string }; + ({ y2:y2 = 5, y3:y3 = { x: 1 } } = {}) +}); + +(function() { + let y4: number, y5: { x: number }; + ({ y4 = 5, y5 = { x: 1 } } = {}) +}); + +(function() { + let y4: number, y5: { x: number }; + ({ y4:y4 = 5, y5:y5 = { x: 1 } } = {}) +}); + + +(function() { + let z; + ({ z = { x: 5 } } = { z: { x: 1 } }); +}); + + +(function() { + let z; + ({ z:z = { x: 5 } } = { z: { x: 1 } }); +}); + +(function() { + let a = { s = 5 }; +}); + +function foo({a = 4, b = { x: 5 }}) { +} + +//// [shorthandPropertyAssignmentsInDestructuring.js] +(function () { + var s0; + for (var _i = 0, _a = [{ s0: 1 }]; _i < _a.length; _i++) { + _b = _a[_i].s0, s0 = _b === void 0 ? 5 : _b; + } + var _b; +}); +(function () { + var s0; + for (var _i = 0, _a = [{ s0: 1 }]; _i < _a.length; _i++) { + _b = _a[_i].s0, s0 = _b === void 0 ? 5 : _b; + } + var _b; +}); +(function () { + var s1; + for (var _i = 0, _a = [{}]; _i < _a.length; _i++) { + _b = _a[_i].s1, s1 = _b === void 0 ? 5 : _b; + } + var _b; +}); +(function () { + var s1; + for (var _i = 0, _a = [{}]; _i < _a.length; _i++) { + _b = _a[_i].s1, s1 = _b === void 0 ? 5 : _b; + } + var _b; +}); +(function () { + var s2; + for (var _i = 0, _a = [{ s2: "" }]; _i < _a.length; _i++) { + _b = _a[_i].s2, s2 = _b === void 0 ? 5 : _b; + } + var _b; +}); +(function () { + var s2; + for (var _i = 0, _a = [{ s2: "" }]; _i < _a.length; _i++) { + _b = _a[_i].s2, s2 = _b === void 0 ? 5 : _b; + } + var _b; +}); +(function () { + var s3; + for (var _i = 0, _a = [{ s3: "" }]; _i < _a.length; _i++) { + _b = _a[_i].s3, s3 = _b === void 0 ? 5 : _b; + } + var _b; +}); +(function () { + var s3; + for (var _i = 0, _a = [{ s3: "" }]; _i < _a.length; _i++) { + _b = _a[_i].s3, s3 = _b === void 0 ? 5 : _b; + } + var _b; +}); +(function () { + var y; + (_a = { y: 1 }, _b = _a.y, y = _b === void 0 ? 5 : _b, _a); + var _a, _b; +}); +(function () { + var y; + (_a = { y: 1 }, _b = _a.y, y = _b === void 0 ? 5 : _b, _a); + var _a, _b; +}); +(function () { + var y0; + (_a = { y0: 1 }, _b = _a.y0, y0 = _b === void 0 ? 5 : _b, _a); + var _a, _b; +}); +(function () { + var y0; + (_a = { y0: 1 }, _b = _a.y0, y0 = _b === void 0 ? 5 : _b, _a); + var _a, _b; +}); +(function () { + var y1; + (_a = {}, _b = _a.y1, y1 = _b === void 0 ? 5 : _b, _a); + var _a, _b; +}); +(function () { + var y1; + (_a = {}, _b = _a.y1, y1 = _b === void 0 ? 5 : _b, _a); + var _a, _b; +}); +(function () { + var y2, y3; + (_a = {}, _b = _a.y2, y2 = _b === void 0 ? 5 : _b, _c = _a.y3, y3 = _c === void 0 ? { x: 1 } : _c, _a); + var _a, _b, _c; +}); +(function () { + var y2, y3; + (_a = {}, _b = _a.y2, y2 = _b === void 0 ? 5 : _b, _c = _a.y3, y3 = _c === void 0 ? { x: 1 } : _c, _a); + var _a, _b, _c; +}); +(function () { + var y4, y5; + (_a = {}, _b = _a.y4, y4 = _b === void 0 ? 5 : _b, _c = _a.y5, y5 = _c === void 0 ? { x: 1 } : _c, _a); + var _a, _b, _c; +}); +(function () { + var y4, y5; + (_a = {}, _b = _a.y4, y4 = _b === void 0 ? 5 : _b, _c = _a.y5, y5 = _c === void 0 ? { x: 1 } : _c, _a); + var _a, _b, _c; +}); +(function () { + var z; + (_a = { z: { x: 1 } }, _b = _a.z, z = _b === void 0 ? { x: 5 } : _b, _a); + var _a, _b; +}); +(function () { + var z; + (_a = { z: { x: 1 } }, _b = _a.z, z = _b === void 0 ? { x: 5 } : _b, _a); + var _a, _b; +}); +(function () { + var a = { s: s }; +}); +function foo(_a) { + var _b = _a.a, a = _b === void 0 ? 4 : _b, _c = _a.b, b = _c === void 0 ? { x: 5 } : _c; +} diff --git a/tests/baselines/reference/shorthandPropertyAssignmentsInDestructuring_ES6.errors.txt b/tests/baselines/reference/shorthandPropertyAssignmentsInDestructuring_ES6.errors.txt new file mode 100644 index 00000000000..7e6b6b35d7f --- /dev/null +++ b/tests/baselines/reference/shorthandPropertyAssignmentsInDestructuring_ES6.errors.txt @@ -0,0 +1,164 @@ +tests/cases/compiler/shorthandPropertyAssignmentsInDestructuring_ES6.ts(16,9): error TS2459: Type '{}' has no property 's1' and no string index signature. +tests/cases/compiler/shorthandPropertyAssignmentsInDestructuring_ES6.ts(22,9): error TS2459: Type '{}' has no property 's1' and no string index signature. +tests/cases/compiler/shorthandPropertyAssignmentsInDestructuring_ES6.ts(40,9): error TS2322: Type 'number' is not assignable to type 'string'. +tests/cases/compiler/shorthandPropertyAssignmentsInDestructuring_ES6.ts(46,12): error TS2322: Type 'number' is not assignable to type 'string'. +tests/cases/compiler/shorthandPropertyAssignmentsInDestructuring_ES6.ts(72,5): error TS2322: Type 'number' is not assignable to type 'string'. +tests/cases/compiler/shorthandPropertyAssignmentsInDestructuring_ES6.ts(77,8): error TS2322: Type 'number' is not assignable to type 'string'. +tests/cases/compiler/shorthandPropertyAssignmentsInDestructuring_ES6.ts(82,5): error TS2322: Type 'number' is not assignable to type 'string'. +tests/cases/compiler/shorthandPropertyAssignmentsInDestructuring_ES6.ts(82,13): error TS2322: Type '{ x: number; }' is not assignable to type '{ x: string; }'. + Types of property 'x' are incompatible. + Type 'number' is not assignable to type 'string'. +tests/cases/compiler/shorthandPropertyAssignmentsInDestructuring_ES6.ts(87,8): error TS2322: Type 'number' is not assignable to type 'string'. +tests/cases/compiler/shorthandPropertyAssignmentsInDestructuring_ES6.ts(87,19): error TS2322: Type '{ x: number; }' is not assignable to type '{ x: string; }'. + Types of property 'x' are incompatible. + Type 'number' is not assignable to type 'string'. +tests/cases/compiler/shorthandPropertyAssignmentsInDestructuring_ES6.ts(113,12): error TS2304: Cannot find name 's'. +tests/cases/compiler/shorthandPropertyAssignmentsInDestructuring_ES6.ts(113,14): error TS1312: '=' can only be used in an object literal property inside a destructuring assignment. + + +==== tests/cases/compiler/shorthandPropertyAssignmentsInDestructuring_ES6.ts (12 errors) ==== + + + (function() { + var s0; + for ({ s0 = 5 } of [{ s0: 1 }]) { + } + }); + (function() { + var s0; + for ({ s0:s0 = 5 } of [{ s0: 1 }]) { + } + }); + + (function() { + var s1; + for ({ s1 = 5 } of [{}]) { + ~~ +!!! error TS2459: Type '{}' has no property 's1' and no string index signature. + } + }); + + (function() { + var s1; + for ({ s1:s1 = 5 } of [{}]) { + ~~ +!!! error TS2459: Type '{}' has no property 's1' and no string index signature. + } + }); + + (function() { + var s2; + for ({ s2 = 5 } of [{ s2: "" }]) { + } + }); + + (function() { + var s2; + for ({ s2:s2 = 5 } of [{ s2: "" }]) { + } + }); + + (function() { + var s3: string; + for ({ s3 = 5 } of [{ s3: "" }]) { + ~~ +!!! error TS2322: Type 'number' is not assignable to type 'string'. + } + }); + + (function() { + var s3: string; + for ({ s3:s3 = 5 } of [{ s3: "" }]) { + ~~ +!!! error TS2322: Type 'number' is not assignable to type 'string'. + } + }); + + (function() { + let y; + ({ y = 5 } = { y: 1 }) + }); + + (function() { + let y; + ({ y:y = 5 } = { y: 1 }) + }); + + (function() { + let y0: number; + ({ y0 = 5 } = { y0: 1 }) + }); + + (function() { + let y0: number; + ({ y0:y0 = 5 } = { y0: 1 }) + }); + + (function() { + let y1: string; + ({ y1 = 5 } = {}) + ~~ +!!! error TS2322: Type 'number' is not assignable to type 'string'. + }); + + (function() { + let y1: string; + ({ y1:y1 = 5 } = {}) + ~~ +!!! error TS2322: Type 'number' is not assignable to type 'string'. + }); + + (function() { + let y2: string, y3: { x: string }; + ({ y2 = 5, y3 = { x: 1 } } = {}) + ~~ +!!! error TS2322: Type 'number' is not assignable to type 'string'. + ~~ +!!! error TS2322: Type '{ x: number; }' is not assignable to type '{ x: string; }'. +!!! error TS2322: Types of property 'x' are incompatible. +!!! error TS2322: Type 'number' is not assignable to type 'string'. + }); + + (function() { + let y2: string, y3: { x: string }; + ({ y2:y2 = 5, y3:y3 = { x: 1 } } = {}) + ~~ +!!! error TS2322: Type 'number' is not assignable to type 'string'. + ~~ +!!! error TS2322: Type '{ x: number; }' is not assignable to type '{ x: string; }'. +!!! error TS2322: Types of property 'x' are incompatible. +!!! error TS2322: Type 'number' is not assignable to type 'string'. + }); + + (function() { + let y4: number, y5: { x: number }; + ({ y4 = 5, y5 = { x: 1 } } = {}) + }); + + (function() { + let y4: number, y5: { x: number }; + ({ y4:y4 = 5, y5:y5 = { x: 1 } } = {}) + }); + + + (function() { + let z; + ({ z = { x: 5 } } = { z: { x: 1 } }); + }); + + + (function() { + let z; + ({ z:z = { x: 5 } } = { z: { x: 1 } }); + }); + + (function() { + let a = { s = 5 }; + ~ +!!! error TS2304: Cannot find name 's'. + ~ +!!! error TS1312: '=' can only be used in an object literal property inside a destructuring assignment. + }); + + function foo({a = 4, b = { x: 5 }}) { + } \ No newline at end of file diff --git a/tests/baselines/reference/shorthandPropertyAssignmentsInDestructuring_ES6.js b/tests/baselines/reference/shorthandPropertyAssignmentsInDestructuring_ES6.js new file mode 100644 index 00000000000..11068708110 --- /dev/null +++ b/tests/baselines/reference/shorthandPropertyAssignmentsInDestructuring_ES6.js @@ -0,0 +1,213 @@ +//// [shorthandPropertyAssignmentsInDestructuring_ES6.ts] + + +(function() { + var s0; + for ({ s0 = 5 } of [{ s0: 1 }]) { + } +}); +(function() { + var s0; + for ({ s0:s0 = 5 } of [{ s0: 1 }]) { + } +}); + +(function() { + var s1; + for ({ s1 = 5 } of [{}]) { + } +}); + +(function() { + var s1; + for ({ s1:s1 = 5 } of [{}]) { + } +}); + +(function() { + var s2; + for ({ s2 = 5 } of [{ s2: "" }]) { + } +}); + +(function() { + var s2; + for ({ s2:s2 = 5 } of [{ s2: "" }]) { + } +}); + +(function() { + var s3: string; + for ({ s3 = 5 } of [{ s3: "" }]) { + } +}); + +(function() { + var s3: string; + for ({ s3:s3 = 5 } of [{ s3: "" }]) { + } +}); + +(function() { + let y; + ({ y = 5 } = { y: 1 }) +}); + +(function() { + let y; + ({ y:y = 5 } = { y: 1 }) +}); + +(function() { + let y0: number; + ({ y0 = 5 } = { y0: 1 }) +}); + +(function() { + let y0: number; + ({ y0:y0 = 5 } = { y0: 1 }) +}); + +(function() { + let y1: string; + ({ y1 = 5 } = {}) +}); + +(function() { + let y1: string; + ({ y1:y1 = 5 } = {}) +}); + +(function() { + let y2: string, y3: { x: string }; + ({ y2 = 5, y3 = { x: 1 } } = {}) +}); + +(function() { + let y2: string, y3: { x: string }; + ({ y2:y2 = 5, y3:y3 = { x: 1 } } = {}) +}); + +(function() { + let y4: number, y5: { x: number }; + ({ y4 = 5, y5 = { x: 1 } } = {}) +}); + +(function() { + let y4: number, y5: { x: number }; + ({ y4:y4 = 5, y5:y5 = { x: 1 } } = {}) +}); + + +(function() { + let z; + ({ z = { x: 5 } } = { z: { x: 1 } }); +}); + + +(function() { + let z; + ({ z:z = { x: 5 } } = { z: { x: 1 } }); +}); + +(function() { + let a = { s = 5 }; +}); + +function foo({a = 4, b = { x: 5 }}) { +} + +//// [shorthandPropertyAssignmentsInDestructuring_ES6.js] +(function () { + var s0; + for ({ s0 = 5 } of [{ s0: 1 }]) { + } +}); +(function () { + var s0; + for ({ s0: s0 = 5 } of [{ s0: 1 }]) { + } +}); +(function () { + var s1; + for ({ s1 = 5 } of [{}]) { + } +}); +(function () { + var s1; + for ({ s1: s1 = 5 } of [{}]) { + } +}); +(function () { + var s2; + for ({ s2 = 5 } of [{ s2: "" }]) { + } +}); +(function () { + var s2; + for ({ s2: s2 = 5 } of [{ s2: "" }]) { + } +}); +(function () { + var s3; + for ({ s3 = 5 } of [{ s3: "" }]) { + } +}); +(function () { + var s3; + for ({ s3: s3 = 5 } of [{ s3: "" }]) { + } +}); +(function () { + let y; + ({ y = 5 } = { y: 1 }); +}); +(function () { + let y; + ({ y: y = 5 } = { y: 1 }); +}); +(function () { + let y0; + ({ y0 = 5 } = { y0: 1 }); +}); +(function () { + let y0; + ({ y0: y0 = 5 } = { y0: 1 }); +}); +(function () { + let y1; + ({ y1 = 5 } = {}); +}); +(function () { + let y1; + ({ y1: y1 = 5 } = {}); +}); +(function () { + let y2, y3; + ({ y2 = 5, y3 = { x: 1 } } = {}); +}); +(function () { + let y2, y3; + ({ y2: y2 = 5, y3: y3 = { x: 1 } } = {}); +}); +(function () { + let y4, y5; + ({ y4 = 5, y5 = { x: 1 } } = {}); +}); +(function () { + let y4, y5; + ({ y4: y4 = 5, y5: y5 = { x: 1 } } = {}); +}); +(function () { + let z; + ({ z = { x: 5 } } = { z: { x: 1 } }); +}); +(function () { + let z; + ({ z: z = { x: 5 } } = { z: { x: 1 } }); +}); +(function () { + let a = { s = 5 }; +}); +function foo({ a = 4, b = { x: 5 } }) { +} diff --git a/tests/cases/compiler/shorthandPropertyAssignmentsInDestructuring.ts b/tests/cases/compiler/shorthandPropertyAssignmentsInDestructuring.ts new file mode 100644 index 00000000000..9750ea5d161 --- /dev/null +++ b/tests/cases/compiler/shorthandPropertyAssignmentsInDestructuring.ts @@ -0,0 +1,118 @@ +// @target: ES5 + + +(function() { + var s0; + for ({ s0 = 5 } of [{ s0: 1 }]) { + } +}); +(function() { + var s0; + for ({ s0:s0 = 5 } of [{ s0: 1 }]) { + } +}); + +(function() { + var s1; + for ({ s1 = 5 } of [{}]) { + } +}); + +(function() { + var s1; + for ({ s1:s1 = 5 } of [{}]) { + } +}); + +(function() { + var s2; + for ({ s2 = 5 } of [{ s2: "" }]) { + } +}); + +(function() { + var s2; + for ({ s2:s2 = 5 } of [{ s2: "" }]) { + } +}); + +(function() { + var s3: string; + for ({ s3 = 5 } of [{ s3: "" }]) { + } +}); + +(function() { + var s3: string; + for ({ s3:s3 = 5 } of [{ s3: "" }]) { + } +}); + +(function() { + let y; + ({ y = 5 } = { y: 1 }) +}); + +(function() { + let y; + ({ y:y = 5 } = { y: 1 }) +}); + +(function() { + let y0: number; + ({ y0 = 5 } = { y0: 1 }) +}); + +(function() { + let y0: number; + ({ y0:y0 = 5 } = { y0: 1 }) +}); + +(function() { + let y1: string; + ({ y1 = 5 } = {}) +}); + +(function() { + let y1: string; + ({ y1:y1 = 5 } = {}) +}); + +(function() { + let y2: string, y3: { x: string }; + ({ y2 = 5, y3 = { x: 1 } } = {}) +}); + +(function() { + let y2: string, y3: { x: string }; + ({ y2:y2 = 5, y3:y3 = { x: 1 } } = {}) +}); + +(function() { + let y4: number, y5: { x: number }; + ({ y4 = 5, y5 = { x: 1 } } = {}) +}); + +(function() { + let y4: number, y5: { x: number }; + ({ y4:y4 = 5, y5:y5 = { x: 1 } } = {}) +}); + + +(function() { + let z; + ({ z = { x: 5 } } = { z: { x: 1 } }); +}); + + +(function() { + let z; + ({ z:z = { x: 5 } } = { z: { x: 1 } }); +}); + +(function() { + let a = { s = 5 }; +}); + +function foo({a = 4, b = { x: 5 }}) { +} \ No newline at end of file diff --git a/tests/cases/compiler/shorthandPropertyAssignmentsInDestructuring_ES6.ts b/tests/cases/compiler/shorthandPropertyAssignmentsInDestructuring_ES6.ts new file mode 100644 index 00000000000..d479511b11d --- /dev/null +++ b/tests/cases/compiler/shorthandPropertyAssignmentsInDestructuring_ES6.ts @@ -0,0 +1,118 @@ +// @target: ES6 + + +(function() { + var s0; + for ({ s0 = 5 } of [{ s0: 1 }]) { + } +}); +(function() { + var s0; + for ({ s0:s0 = 5 } of [{ s0: 1 }]) { + } +}); + +(function() { + var s1; + for ({ s1 = 5 } of [{}]) { + } +}); + +(function() { + var s1; + for ({ s1:s1 = 5 } of [{}]) { + } +}); + +(function() { + var s2; + for ({ s2 = 5 } of [{ s2: "" }]) { + } +}); + +(function() { + var s2; + for ({ s2:s2 = 5 } of [{ s2: "" }]) { + } +}); + +(function() { + var s3: string; + for ({ s3 = 5 } of [{ s3: "" }]) { + } +}); + +(function() { + var s3: string; + for ({ s3:s3 = 5 } of [{ s3: "" }]) { + } +}); + +(function() { + let y; + ({ y = 5 } = { y: 1 }) +}); + +(function() { + let y; + ({ y:y = 5 } = { y: 1 }) +}); + +(function() { + let y0: number; + ({ y0 = 5 } = { y0: 1 }) +}); + +(function() { + let y0: number; + ({ y0:y0 = 5 } = { y0: 1 }) +}); + +(function() { + let y1: string; + ({ y1 = 5 } = {}) +}); + +(function() { + let y1: string; + ({ y1:y1 = 5 } = {}) +}); + +(function() { + let y2: string, y3: { x: string }; + ({ y2 = 5, y3 = { x: 1 } } = {}) +}); + +(function() { + let y2: string, y3: { x: string }; + ({ y2:y2 = 5, y3:y3 = { x: 1 } } = {}) +}); + +(function() { + let y4: number, y5: { x: number }; + ({ y4 = 5, y5 = { x: 1 } } = {}) +}); + +(function() { + let y4: number, y5: { x: number }; + ({ y4:y4 = 5, y5:y5 = { x: 1 } } = {}) +}); + + +(function() { + let z; + ({ z = { x: 5 } } = { z: { x: 1 } }); +}); + + +(function() { + let z; + ({ z:z = { x: 5 } } = { z: { x: 1 } }); +}); + +(function() { + let a = { s = 5 }; +}); + +function foo({a = 4, b = { x: 5 }}) { +} \ No newline at end of file