@@ -722,6 +722,7 @@ namespace ts {
722
722
NoIndexSignatures = 1 << 0,
723
723
Writing = 1 << 1,
724
724
CacheSymbol = 1 << 2,
725
+ NoTupleBoundsCheck = 1 << 3,
725
726
}
726
727
727
728
const enum CallbackCheck {
@@ -5115,21 +5116,25 @@ namespace ts {
5115
5116
}
5116
5117
else if (isArrayLikeType(parentType)) {
5117
5118
const indexType = getLiteralType(index);
5118
- const declaredType = getConstraintForLocation(getIndexedAccessType(parentType, indexType, declaration.name), declaration.name);
5119
+ const accessFlags = hasDefaultValue(declaration) ? AccessFlags.NoTupleBoundsCheck : 0;
5120
+ const declaredType = getConstraintForLocation(getIndexedAccessTypeOrUndefined(parentType, indexType, declaration.name, accessFlags) || errorType, declaration.name);
5119
5121
type = getFlowTypeOfDestructuring(declaration, declaredType);
5120
5122
}
5121
5123
else {
5122
5124
type = elementType;
5123
5125
}
5124
5126
}
5125
- // In strict null checking mode, if a default value of a non-undefined type is specified, remove
5126
- // undefined from the final type.
5127
- if (strictNullChecks && declaration.initializer && !(getFalsyFlags(checkDeclarationInitializer(declaration)) & TypeFlags.Undefined)) {
5128
- type = getTypeWithFacts(type, TypeFacts.NEUndefined);
5127
+ if (!declaration.initializer) {
5128
+ return type;
5129
5129
}
5130
- return declaration.initializer && !getEffectiveTypeAnnotationNode(walkUpBindingElementsAndPatterns(declaration)) ?
5131
- getUnionType([type, checkDeclarationInitializer(declaration)], UnionReduction.Subtype) :
5132
- type;
5130
+ if (getEffectiveTypeAnnotationNode(walkUpBindingElementsAndPatterns(declaration))) {
5131
+ // In strict null checking mode, if a default value of a non-undefined type is specified, remove
5132
+ // undefined from the final type.
5133
+ return strictNullChecks && !(getFalsyFlags(checkDeclarationInitializer(declaration)) & TypeFlags.Undefined) ?
5134
+ getTypeWithFacts(type, TypeFacts.NEUndefined) :
5135
+ type;
5136
+ }
5137
+ return getUnionType([getTypeWithFacts(type, TypeFacts.NEUndefined), checkDeclarationInitializer(declaration)], UnionReduction.Subtype);
5133
5138
}
5134
5139
5135
5140
function getTypeForDeclarationFromJSDocComment(declaration: Node) {
@@ -10131,7 +10136,7 @@ namespace ts {
10131
10136
propType;
10132
10137
}
10133
10138
if (everyType(objectType, isTupleType) && isNumericLiteralName(propName) && +propName >= 0) {
10134
- if (accessNode && everyType(objectType, t => !(<TupleTypeReference>t).target.hasRestElement)) {
10139
+ if (accessNode && everyType(objectType, t => !(<TupleTypeReference>t).target.hasRestElement) && !(accessFlags & AccessFlags.NoTupleBoundsCheck) ) {
10135
10140
const indexNode = getIndexNodeForAccessExpression(accessNode);
10136
10141
if (isTupleType(objectType)) {
10137
10142
error(indexNode, Diagnostics.Tuple_type_0_of_length_1_has_no_element_at_index_2,
@@ -19196,26 +19201,7 @@ namespace ts {
19196
19201
function getArrayLiteralTupleTypeIfApplicable(elementTypes: Type[], contextualType: Type | undefined, hasRestElement: boolean, elementCount = elementTypes.length, readonly = false) {
19197
19202
// Infer a tuple type when the contextual type is or contains a tuple-like type
19198
19203
if (readonly || (contextualType && forEachType(contextualType, isTupleLikeType))) {
19199
- const minLength = elementCount - (hasRestElement ? 1 : 0);
19200
- const pattern = contextualType && contextualType.pattern;
19201
- // If array literal is contextually typed by a binding pattern or an assignment pattern, pad the resulting
19202
- // tuple type with the corresponding binding or assignment element types to make the lengths equal.
19203
- if (!hasRestElement && pattern && (pattern.kind === SyntaxKind.ArrayBindingPattern || pattern.kind === SyntaxKind.ArrayLiteralExpression)) {
19204
- const patternElements = (<BindingPattern | ArrayLiteralExpression>pattern).elements;
19205
- for (let i = elementCount; i < patternElements.length; i++) {
19206
- const e = patternElements[i];
19207
- if (hasDefaultValue(e)) {
19208
- elementTypes.push((<TypeReference>contextualType).typeArguments![i]);
19209
- }
19210
- else if (i < patternElements.length - 1 || !(e.kind === SyntaxKind.BindingElement && (<BindingElement>e).dotDotDotToken || e.kind === SyntaxKind.SpreadElement)) {
19211
- if (e.kind !== SyntaxKind.OmittedExpression) {
19212
- error(e, Diagnostics.Initializer_provides_no_value_for_this_binding_element_and_the_binding_element_has_no_default_value);
19213
- }
19214
- elementTypes.push(strictNullChecks ? implicitNeverType : undefinedWideningType);
19215
- }
19216
- }
19217
- }
19218
- return createTupleType(elementTypes, minLength, hasRestElement, readonly);
19204
+ return createTupleType(elementTypes, elementCount - (hasRestElement ? 1 : 0), hasRestElement, readonly);
19219
19205
}
19220
19206
}
19221
19207
@@ -23655,8 +23641,10 @@ namespace ts {
23655
23641
if (isArrayLikeType(sourceType)) {
23656
23642
// We create a synthetic expression so that getIndexedAccessType doesn't get confused
23657
23643
// when the element is a SyntaxKind.ElementAccessExpression.
23658
- const elementType = getIndexedAccessType(sourceType, indexType, createSyntheticExpression(element, indexType));
23659
- const type = getFlowTypeOfDestructuring(element, elementType);
23644
+ const accessFlags = hasDefaultValue(element) ? AccessFlags.NoTupleBoundsCheck : 0;
23645
+ const elementType = getIndexedAccessTypeOrUndefined(sourceType, indexType, createSyntheticExpression(element, indexType), accessFlags) || errorType;
23646
+ const assignedType = hasDefaultValue(element) ? getTypeWithFacts(elementType, TypeFacts.NEUndefined) : elementType;
23647
+ const type = getFlowTypeOfDestructuring(element, assignedType);
23660
23648
return checkDestructuringAssignment(element, type, checkMode);
23661
23649
}
23662
23650
return checkDestructuringAssignment(element, elementType, checkMode);
0 commit comments