diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 4e93ea1c157..03df66502dd 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -150,6 +150,8 @@ module ts { var globalRegExpType: ObjectType; var globalTemplateStringsArrayType: ObjectType; + var anyArrayType: Type; + var tupleTypes: Map = {}; var unionTypes: Map = {}; var stringLiteralTypes: Map = {}; @@ -1643,24 +1645,24 @@ module ts { getIndexTypeOfType(parentType, IndexKind.String); if (!type) { error(name, Diagnostics.Type_0_has_no_property_1_and_no_string_index_signature, typeToString(parentType), declarationNameToString(name)); + return unknownType; } + return type; } - else { - if (getPropertyOfType(parentType, "0")) { - var propName = "" + indexOf(pattern.elements, declaration); - var type = getTypeOfPropertyOfType(parentType, propName); - if (!type) { - error(declaration, Diagnostics.Type_0_has_no_property_1, typeToString(parentType), propName); - } - } - else { - var type = getIndexTypeOfType(parentType, IndexKind.Number); - if (!type) { - error(declaration, Diagnostics.Type_0_has_no_numeric_index_signature, typeToString(parentType)); - } - } + if (!isTypeAssignableTo(parentType, anyArrayType)) { + error(pattern, Diagnostics.Type_0_is_not_an_array_type, typeToString(parentType)); + return unknownType; } - return type || unknownType; + if (isTupleType(parentType)) { + var propName = "" + indexOf(pattern.elements, declaration); + var type = getTypeOfPropertyOfType(parentType, propName); + if (!type) { + error(declaration, Diagnostics.Type_0_has_no_property_1, typeToString(parentType), propName); + return unknownType; + } + return type; + } + return getIndexTypeOfType(parentType, IndexKind.Number); } function getTypeForVariableDeclaration(declaration: VariableDeclaration | PropertyDeclaration): Type { @@ -1739,7 +1741,8 @@ module ts { if (isBindingPattern(declaration.name)) { return getTypeFromBindingPattern(declaration.name); } - // Rest parameters default to type any[], other parameters default to type any type = declaration.flags & NodeFlags.Rest ? createArrayType(anyType) : anyType; + // Rest parameters default to type any[], other parameters default to type any + type = declaration.flags & NodeFlags.Rest ? anyArrayType : anyType; // Report implicit any errors unless this is a private property within an ambient declaration if (reportErrors && compilerOptions.noImplicitAny && !isPrivateWithinAmbient(declaration) && !(declaration.kind === SyntaxKind.Parameter && isPrivateWithinAmbient(declaration.parent))) { reportImplicitAnyError(declaration, type); @@ -3976,6 +3979,10 @@ module ts { return type.flags & TypeFlags.Reference && (type).target === globalArrayType; } + function isTupleType(type: Type): boolean { + return (type.flags & TypeFlags.Tuple) !== 0; + } + function getWidenedTypeOfObjectLiteral(type: Type): Type { var properties = getPropertiesOfObjectType(type); var members: SymbolTable = {}; @@ -4914,7 +4921,7 @@ module ts { // Return true if the given contextual type is a tuple-like type function contextualTypeIsTupleType(type: Type): boolean { - return !!(type.flags & TypeFlags.Union ? forEach((type).types, t => getPropertyOfObjectType(t, "0")) : getPropertyOfObjectType(type, "0")); + return !!(type.flags & TypeFlags.Union ? forEach((type).types, t => isTupleType(t)) : isTupleType(type)); } // Return true if the given contextual type provides an index signature of the given kind @@ -6379,12 +6386,11 @@ module ts { } function checkArrayLiteralAssignment(node: ArrayLiteral, sourceType: Type, contextualMapper?: TypeMapper): Type { - var isTupleType = getPropertyOfType(sourceType, "0"); var elements = node.elements; for (var i = 0; i < elements.length; i++) { var e = elements[i]; if (e.kind !== SyntaxKind.OmittedExpression) { - if (isTupleType) { + if (isTupleType(sourceType)) { var propName = "" + i; var type = getTypeOfPropertyOfType(sourceType, propName); if (!type) { @@ -9290,12 +9296,12 @@ module ts { globalNumberType = getGlobalType("Number"); globalBooleanType = getGlobalType("Boolean"); globalRegExpType = getGlobalType("RegExp"); - // If we're in ES6 mode, load the TemplateStringsArray. // Otherwise, default to 'unknown' for the purposes of type checking in LS scenarios. globalTemplateStringsArrayType = compilerOptions.target >= ScriptTarget.ES6 ? getGlobalType("TemplateStringsArray") : unknownType; + anyArrayType = createArrayType(anyType); } initializeTypeChecker(); diff --git a/src/compiler/diagnosticInformationMap.generated.ts b/src/compiler/diagnosticInformationMap.generated.ts index 0ab30ca4dcd..2ff4be92fd2 100644 --- a/src/compiler/diagnosticInformationMap.generated.ts +++ b/src/compiler/diagnosticInformationMap.generated.ts @@ -281,6 +281,7 @@ module ts { Type_0_has_no_property_1_and_no_string_index_signature: { code: 2459, category: DiagnosticCategory.Error, key: "Type '{0}' has no property '{1}' and no string index signature." }, Type_0_has_no_property_1: { code: 2460, category: DiagnosticCategory.Error, key: "Type '{0}' has no property '{1}'." }, Type_0_has_no_numeric_index_signature: { code: 2461, category: DiagnosticCategory.Error, key: "Type '{0}' has no numeric index signature." }, + Type_0_is_not_an_array_type: { code: 2462, category: DiagnosticCategory.Error, key: "Type '{0}' is not an array type." }, Import_declaration_0_is_using_private_name_1: { code: 4000, category: DiagnosticCategory.Error, key: "Import declaration '{0}' is using private name '{1}'." }, Type_parameter_0_of_exported_class_has_or_is_using_name_1_from_private_module_2: { code: 4001, category: DiagnosticCategory.Error, key: "Type parameter '{0}' of exported class has or is using name '{1}' from private module '{2}'." }, Type_parameter_0_of_exported_class_has_or_is_using_private_name_1: { code: 4002, category: DiagnosticCategory.Error, key: "Type parameter '{0}' of exported class has or is using private name '{1}'." }, diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 9a704ea948e..e56188eae9f 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -1120,6 +1120,10 @@ "category": "Error", "code": 2461 }, + "Type '{0}' is not an array type.": { + "category": "Error", + "code": 2462 + }, "Import declaration '{0}' is using private name '{1}'.": { "category": "Error", diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 7b88bfde451..e7df9e9136a 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -1534,11 +1534,22 @@ module ts { function emitParameter(node: ParameterDeclaration) { emitLeadingComments(node); - if (node.propertyName) { - emit(node.propertyName); - write(": "); + if (compilerOptions.target < ScriptTarget.ES6) { + if (isBindingPattern(node.name)) { + write("__" + indexOf((node.parent).parameters, node)); + } + else { + emit(node.name); + } + } + else { + if (node.propertyName) { + emit(node.propertyName); + write(": "); + } + emit(node.name); + //emitOptional(" = ", node.initializer); } - emit(node.name); emitTrailingComments(node); } diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 6c99d1ae61e..7fd68b9ce03 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -1250,11 +1250,11 @@ module ts { return lookAhead(isClassMemberStart); case ParsingContext.EnumMembers: case ParsingContext.ObjectLiteralMembers: + case ParsingContext.ObjectBindingElements: return isPropertyName(); case ParsingContext.BaseTypeReferences: return isIdentifier() && ((token !== SyntaxKind.ExtendsKeyword && token !== SyntaxKind.ImplementsKeyword) || !lookAhead(() => (nextToken(), isIdentifier()))); case ParsingContext.VariableDeclarations: - case ParsingContext.ObjectBindingElements: return isIdentifierOrPattern(); case ParsingContext.ArrayBindingElements: return token === SyntaxKind.CommaToken || isIdentifierOrPattern(); @@ -3477,13 +3477,14 @@ module ts { var node = createNode(kind); node.flags = flags; if (context === ParsingContext.ObjectBindingElements) { - var id = parseIdentifier(); - if (parseOptional(SyntaxKind.ColonToken)) { - node.propertyName = id; - node.name = parseIdentifierOrPattern(kind, flags); + var id = parsePropertyName(); + if (id.kind === SyntaxKind.Identifier && token !== SyntaxKind.ColonToken) { + node.name = id; } else { - node.name = id; + parseExpected(SyntaxKind.ColonToken); + node.propertyName = id; + node.name = parseIdentifierOrPattern(kind, flags); } } else {