@@ -4827,21 +4827,13 @@ namespace ts {
4827
4827
mapType(parentType, t => sliceTupleType(<TupleTypeReference>t, index)) :
4828
4828
createArrayType(elementType);
4829
4829
}
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
+ }
4830
4835
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;
4845
4837
}
4846
4838
}
4847
4839
// In strict null checking mode, if a default value of a non-undefined type is specified, remove
@@ -9523,7 +9515,7 @@ namespace ts {
9523
9515
return false;
9524
9516
}
9525
9517
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) {
9527
9519
const accessExpression = accessNode && accessNode.kind === SyntaxKind.ElementAccessExpression ? accessNode : undefined;
9528
9520
const propName = isTypeUsableAsLateBoundName(indexType)
9529
9521
? getLateBoundNameFromType(indexType)
@@ -9626,7 +9618,7 @@ namespace ts {
9626
9618
return missingType;
9627
9619
}
9628
9620
9629
- function getIndexNodeForAccessExpression(accessNode: ElementAccessExpression | IndexedAccessTypeNode | PropertyName) {
9621
+ function getIndexNodeForAccessExpression(accessNode: ElementAccessExpression | IndexedAccessTypeNode | PropertyName | SyntheticExpression ) {
9630
9622
return accessNode.kind === SyntaxKind.ElementAccessExpression
9631
9623
? accessNode.argumentExpression
9632
9624
: accessNode.kind === SyntaxKind.IndexedAccessType
@@ -9695,7 +9687,7 @@ namespace ts {
9695
9687
return type.simplified = type;
9696
9688
}
9697
9689
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 {
9699
9691
if (objectType === wildcardType || indexType === wildcardType) {
9700
9692
return wildcardType;
9701
9693
}
@@ -14628,7 +14620,7 @@ namespace ts {
14628
14620
getAccessedPropertyName(source as PropertyAccessExpression | ElementAccessExpression) === getAccessedPropertyName(target) &&
14629
14621
isMatchingReference((source as PropertyAccessExpression | ElementAccessExpression).expression, target.expression);
14630
14622
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 )) {
14632
14624
const ancestor = source.parent.parent;
14633
14625
if (ancestor.kind === SyntaxKind.BindingElement) {
14634
14626
return isMatchingReference(ancestor, (<PropertyAccessExpression>target).expression);
@@ -22010,21 +22002,17 @@ namespace ts {
22010
22002
function checkObjectLiteralDestructuringPropertyAssignment(objectLiteralType: Type, property: ObjectLiteralElementLike, allProperties?: NodeArray<ObjectLiteralElementLike>, rightIsThis = false) {
22011
22003
if (property.kind === SyntaxKind.PropertyAssignment || property.kind === SyntaxKind.ShorthandPropertyAssignment) {
22012
22004
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
+ }
22027
22012
}
22013
+ const exprType = getLiteralTypeFromPropertyName(name);
22014
+ const type = getIndexedAccessType(objectLiteralType, exprType, name);
22015
+ return checkDestructuringAssignment(property.kind === SyntaxKind.ShorthandPropertyAssignment ? property : property.initializer, type);
22028
22016
}
22029
22017
else if (property.kind === SyntaxKind.SpreadAssignment) {
22030
22018
if (languageVersion < ScriptTarget.ESNext) {
@@ -22045,31 +22033,11 @@ namespace ts {
22045
22033
}
22046
22034
}
22047
22035
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
-
22067
22036
function checkArrayLiteralAssignment(node: ArrayLiteralExpression, sourceType: Type, checkMode?: CheckMode): Type {
22068
22037
const elements = node.elements;
22069
22038
if (languageVersion < ScriptTarget.ES2015 && compilerOptions.downlevelIteration) {
22070
22039
checkExternalEmitHelpers(node, ExternalEmitHelpers.Read);
22071
22040
}
22072
-
22073
22041
// This elementType will be used if the specific property corresponding to this index is not
22074
22042
// present (aka the tuple element property). This call also checks that the parentType is in
22075
22043
// fact an iterable or array (depending on target language).
@@ -22086,39 +22054,26 @@ namespace ts {
22086
22054
const element = elements[elementIndex];
22087
22055
if (element.kind !== SyntaxKind.OmittedExpression) {
22088
22056
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) ) :
22092
22060
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);
22105
22065
}
22106
22066
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);
22109
22070
}
22110
22071
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);
22122
22077
}
22123
22078
}
22124
22079
}
0 commit comments