@@ -4827,21 +4827,13 @@ namespace ts {
48274827 mapType(parentType, t => sliceTupleType(<TupleTypeReference>t, index)) :
48284828 createArrayType(elementType);
48294829 }
4830+ else if (isArrayLikeType(parentType)) {
4831+ const indexType = getLiteralType(index);
4832+ const declaredType = getIndexedAccessType(parentType, indexType, createSyntheticExpression(declaration.name, indexType));
4833+ type = getFlowTypeOfReference(declaration, getConstraintForLocation(declaredType, declaration.name));
4834+ }
48304835 else {
4831- // Use specific property type when parent is a tuple or numeric index type when parent is an array
4832- const index = pattern.elements.indexOf(declaration);
4833- type = everyType(parentType, isTupleLikeType) ?
4834- getTupleElementType(parentType, index) || declaration.initializer && checkDeclarationInitializer(declaration) :
4835- elementType;
4836- if (!type) {
4837- if (isTupleType(parentType)) {
4838- error(declaration, Diagnostics.Tuple_type_0_with_length_1_cannot_be_assigned_to_tuple_with_length_2, typeToString(parentType), getTypeReferenceArity(<TypeReference>parentType), pattern.elements.length);
4839- }
4840- else {
4841- error(declaration, Diagnostics.Type_0_has_no_property_1, typeToString(parentType), "" + index);
4842- }
4843- return errorType;
4844- }
4836+ type = elementType;
48454837 }
48464838 }
48474839 // In strict null checking mode, if a default value of a non-undefined type is specified, remove
@@ -9523,7 +9515,7 @@ namespace ts {
95239515 return false;
95249516 }
95259517
9526- function getPropertyTypeForIndexType(objectType: Type, indexType: Type, accessNode: ElementAccessExpression | IndexedAccessTypeNode | PropertyName | undefined, cacheSymbol: boolean, missingType: Type) {
9518+ function getPropertyTypeForIndexType(objectType: Type, indexType: Type, accessNode: ElementAccessExpression | IndexedAccessTypeNode | PropertyName | SyntheticExpression | undefined, cacheSymbol: boolean, missingType: Type) {
95279519 const accessExpression = accessNode && accessNode.kind === SyntaxKind.ElementAccessExpression ? accessNode : undefined;
95289520 const propName = isTypeUsableAsLateBoundName(indexType)
95299521 ? getLateBoundNameFromType(indexType)
@@ -9626,7 +9618,7 @@ namespace ts {
96269618 return missingType;
96279619 }
96289620
9629- function getIndexNodeForAccessExpression(accessNode: ElementAccessExpression | IndexedAccessTypeNode | PropertyName) {
9621+ function getIndexNodeForAccessExpression(accessNode: ElementAccessExpression | IndexedAccessTypeNode | PropertyName | SyntheticExpression ) {
96309622 return accessNode.kind === SyntaxKind.ElementAccessExpression
96319623 ? accessNode.argumentExpression
96329624 : accessNode.kind === SyntaxKind.IndexedAccessType
@@ -9695,7 +9687,7 @@ namespace ts {
96959687 return type.simplified = type;
96969688 }
96979689
9698- function getIndexedAccessType(objectType: Type, indexType: Type, accessNode?: ElementAccessExpression | IndexedAccessTypeNode | PropertyName, missingType = accessNode ? errorType : unknownType): Type {
9690+ function getIndexedAccessType(objectType: Type, indexType: Type, accessNode?: ElementAccessExpression | IndexedAccessTypeNode | PropertyName | SyntheticExpression , missingType = accessNode ? errorType : unknownType): Type {
96999691 if (objectType === wildcardType || indexType === wildcardType) {
97009692 return wildcardType;
97019693 }
@@ -14628,7 +14620,7 @@ namespace ts {
1462814620 getAccessedPropertyName(source as PropertyAccessExpression | ElementAccessExpression) === getAccessedPropertyName(target) &&
1462914621 isMatchingReference((source as PropertyAccessExpression | ElementAccessExpression).expression, target.expression);
1463014622 case SyntaxKind.BindingElement:
14631- if (target.kind === SyntaxKind.PropertyAccessExpression && (<PropertyAccessExpression>target).name.escapedText === getBindingElementNameText(<BindingElement>source )) {
14623+ if ((isPropertyAccessExpression( target) || isElementAccessExpression(target)) && getBindingElementNameText(<BindingElement>source) === getAccessedPropertyName(target )) {
1463214624 const ancestor = source.parent.parent;
1463314625 if (ancestor.kind === SyntaxKind.BindingElement) {
1463414626 return isMatchingReference(ancestor, (<PropertyAccessExpression>target).expression);
@@ -22010,21 +22002,17 @@ namespace ts {
2201022002 function checkObjectLiteralDestructuringPropertyAssignment(objectLiteralType: Type, property: ObjectLiteralElementLike, allProperties?: NodeArray<ObjectLiteralElementLike>, rightIsThis = false) {
2201122003 if (property.kind === SyntaxKind.PropertyAssignment || property.kind === SyntaxKind.ShorthandPropertyAssignment) {
2201222004 const name = property.name;
22013- if (name.kind === SyntaxKind.ComputedPropertyName) {
22014- checkComputedPropertyName(name);
22015- }
22016- if (isComputedNonLiteralName(name)) {
22017- return undefined;
22018- }
22019-
22020- const type = getTypeOfObjectLiteralDestructuringProperty(objectLiteralType, name, property, rightIsThis);
22021- if (type) {
22022- // non-shorthand property assignments should always have initializers
22023- return checkDestructuringAssignment(property.kind === SyntaxKind.ShorthandPropertyAssignment ? property : property.initializer, type);
22024- }
22025- else {
22026- error(name, Diagnostics.Type_0_has_no_property_1_and_no_string_index_signature, typeToString(objectLiteralType), declarationNameToString(name));
22005+ const text = getTextOfPropertyName(name);
22006+ if (text) {
22007+ const prop = getPropertyOfType(objectLiteralType, text);
22008+ if (prop) {
22009+ markPropertyAsReferenced(prop, property, rightIsThis);
22010+ checkPropertyAccessibility(property, /*isSuper*/ false, objectLiteralType, prop);
22011+ }
2202722012 }
22013+ const exprType = getLiteralTypeFromPropertyName(name);
22014+ const type = getIndexedAccessType(objectLiteralType, exprType, name);
22015+ return checkDestructuringAssignment(property.kind === SyntaxKind.ShorthandPropertyAssignment ? property : property.initializer, type);
2202822016 }
2202922017 else if (property.kind === SyntaxKind.SpreadAssignment) {
2203022018 if (languageVersion < ScriptTarget.ESNext) {
@@ -22045,31 +22033,11 @@ namespace ts {
2204522033 }
2204622034 }
2204722035
22048- function getTypeOfObjectLiteralDestructuringProperty(objectLiteralType: Type, name: PropertyName, property: PropertyAssignment | ShorthandPropertyAssignment, rightIsThis: boolean) {
22049- if (isTypeAny(objectLiteralType)) {
22050- return objectLiteralType;
22051- }
22052-
22053- let type: Type | undefined;
22054- const text = getTextOfPropertyName(name);
22055- if (text) { // TODO: GH#26379
22056- const prop = getPropertyOfType(objectLiteralType, text);
22057- if (prop) {
22058- markPropertyAsReferenced(prop, property, rightIsThis);
22059- checkPropertyAccessibility(property, /*isSuper*/ false, objectLiteralType, prop);
22060- type = getTypeOfSymbol(prop);
22061- }
22062- type = type || (isNumericLiteralName(text) ? getIndexTypeOfType(objectLiteralType, IndexKind.Number) : undefined);
22063- }
22064- return type || getIndexTypeOfType(objectLiteralType, IndexKind.String);
22065- }
22066-
2206722036 function checkArrayLiteralAssignment(node: ArrayLiteralExpression, sourceType: Type, checkMode?: CheckMode): Type {
2206822037 const elements = node.elements;
2206922038 if (languageVersion < ScriptTarget.ES2015 && compilerOptions.downlevelIteration) {
2207022039 checkExternalEmitHelpers(node, ExternalEmitHelpers.Read);
2207122040 }
22072-
2207322041 // This elementType will be used if the specific property corresponding to this index is not
2207422042 // present (aka the tuple element property). This call also checks that the parentType is in
2207522043 // fact an iterable or array (depending on target language).
@@ -22086,39 +22054,26 @@ namespace ts {
2208622054 const element = elements[elementIndex];
2208722055 if (element.kind !== SyntaxKind.OmittedExpression) {
2208822056 if (element.kind !== SyntaxKind.SpreadElement) {
22089- const propName = "" + elementIndex as __String ;
22090- const type = isTypeAny (sourceType) ? sourceType :
22091- everyType (sourceType, isTupleLikeType) ? getTupleElementType(sourceType, elementIndex ) :
22057+ const indexType = getLiteralType( elementIndex) ;
22058+ const type = isArrayLikeType (sourceType) ?
22059+ getIndexedAccessType (sourceType, indexType, createSyntheticExpression(element, indexType) ) :
2209222060 elementType;
22093- if (type) {
22094- return checkDestructuringAssignment(element, type, checkMode);
22095- }
22096- // We still need to check element expression here because we may need to set appropriate flag on the expression
22097- // such as NodeCheckFlags.LexicalThis on "this"expression.
22098- checkExpression(element);
22099- if (isTupleType(sourceType)) {
22100- error(element, Diagnostics.Tuple_type_0_with_length_1_cannot_be_assigned_to_tuple_with_length_2, typeToString(sourceType), getTypeReferenceArity(<TypeReference>sourceType), elements.length);
22101- }
22102- else {
22103- error(element, Diagnostics.Type_0_has_no_property_1, typeToString(sourceType), propName as string);
22104- }
22061+ return checkDestructuringAssignment(element, type, checkMode);
22062+ }
22063+ if (elementIndex < elements.length - 1) {
22064+ error(element, Diagnostics.A_rest_element_must_be_last_in_a_destructuring_pattern);
2210522065 }
2210622066 else {
22107- if (elementIndex < elements.length - 1) {
22108- error(element, Diagnostics.A_rest_element_must_be_last_in_a_destructuring_pattern);
22067+ const restExpression = (<SpreadElement>element).expression;
22068+ if (restExpression.kind === SyntaxKind.BinaryExpression && (<BinaryExpression>restExpression).operatorToken.kind === SyntaxKind.EqualsToken) {
22069+ error((<BinaryExpression>restExpression).operatorToken, Diagnostics.A_rest_element_cannot_have_an_initializer);
2210922070 }
2211022071 else {
22111- const restExpression = (<SpreadElement>element).expression;
22112- if (restExpression.kind === SyntaxKind.BinaryExpression && (<BinaryExpression>restExpression).operatorToken.kind === SyntaxKind.EqualsToken) {
22113- error((<BinaryExpression>restExpression).operatorToken, Diagnostics.A_rest_element_cannot_have_an_initializer);
22114- }
22115- else {
22116- checkGrammarForDisallowedTrailingComma(node.elements, Diagnostics.A_rest_parameter_or_binding_pattern_may_not_have_a_trailing_comma);
22117- const type = everyType(sourceType, isTupleType) ?
22118- mapType(sourceType, t => sliceTupleType(<TupleTypeReference>t, elementIndex)) :
22119- createArrayType(elementType);
22120- return checkDestructuringAssignment(restExpression, type, checkMode);
22121- }
22072+ checkGrammarForDisallowedTrailingComma(node.elements, Diagnostics.A_rest_parameter_or_binding_pattern_may_not_have_a_trailing_comma);
22073+ const type = everyType(sourceType, isTupleType) ?
22074+ mapType(sourceType, t => sliceTupleType(<TupleTypeReference>t, elementIndex)) :
22075+ createArrayType(elementType);
22076+ return checkDestructuringAssignment(restExpression, type, checkMode);
2212222077 }
2212322078 }
2212422079 }
0 commit comments