@@ -4628,6 +4628,10 @@ namespace ts {
4628
4628
if (isTypeAny(parentType)) {
4629
4629
return parentType;
4630
4630
}
4631
+ // Relax null check on ambient destructuring parameters, since the parameters have no implementation and are just documentation
4632
+ if (strictNullChecks && declaration.flags & NodeFlags.Ambient && isParameterDeclaration(declaration)) {
4633
+ parentType = getNonNullableType(parentType);
4634
+ }
4631
4635
4632
4636
let type: Type | undefined;
4633
4637
if (pattern.kind === SyntaxKind.ObjectBindingPattern) {
@@ -4647,53 +4651,13 @@ namespace ts {
4647
4651
else {
4648
4652
// Use explicitly specified property name ({ p: xxx } form), or otherwise the implied name ({ p } form)
4649
4653
const name = declaration.propertyName || <Identifier>declaration.name;
4650
- const isLate = isLateBindableName(name);
4651
- const isWellKnown = isComputedPropertyName(name) && isWellKnownSymbolSyntactically(name.expression);
4652
- if (!isLate && !isWellKnown && isComputedNonLiteralName(name)) {
4653
- const exprType = checkExpression((name as ComputedPropertyName).expression);
4654
- if (isTypeAssignableToKind(exprType, TypeFlags.ESSymbolLike)) {
4655
- if (noImplicitAny) {
4656
- error(declaration, Diagnostics.Type_0_cannot_be_used_to_index_type_1, typeToString(exprType), typeToString(parentType));
4657
- }
4658
- return anyType;
4659
- }
4660
- const indexerType = isTypeAssignableToKind(exprType, TypeFlags.NumberLike) && getIndexTypeOfType(parentType, IndexKind.Number) || getIndexTypeOfType(parentType, IndexKind.String);
4661
- if (!indexerType && noImplicitAny && !compilerOptions.suppressImplicitAnyIndexErrors) {
4662
- if (getIndexTypeOfType(parentType, IndexKind.Number)) {
4663
- error(declaration, Diagnostics.Element_implicitly_has_an_any_type_because_index_expression_is_not_of_type_number);
4664
- }
4665
- else {
4666
- error(declaration, Diagnostics.Element_implicitly_has_an_any_type_because_type_0_has_no_index_signature, typeToString(parentType));
4667
- }
4668
- }
4669
- return indexerType || anyType;
4670
- }
4671
-
4672
- // Use type of the specified property, or otherwise, for a numeric name, the type of the numeric index signature,
4673
- // or otherwise the type of the string index signature.
4674
- const nameType = isLate ? checkComputedPropertyName(name as ComputedPropertyName) as LiteralType | UniqueESSymbolType : undefined;
4675
- const text = isLate ? getLateBoundNameFromType(nameType!) :
4676
- isWellKnown ? getPropertyNameForKnownSymbolName(idText(((name as ComputedPropertyName).expression as PropertyAccessExpression).name)) :
4677
- getTextOfPropertyName(name);
4678
-
4679
- // Relax null check on ambient destructuring parameters, since the parameters have no implementation and are just documentation
4680
- if (strictNullChecks && declaration.flags & NodeFlags.Ambient && isParameterDeclaration(declaration)) {
4681
- parentType = getNonNullableType(parentType);
4682
- }
4683
- if (isLate && nameType && !getPropertyOfType(parentType, text) && isTypeAssignableToKind(nameType, TypeFlags.ESSymbolLike)) {
4684
- if (noImplicitAny) {
4685
- error(declaration, Diagnostics.Type_0_cannot_be_used_to_index_type_1, typeToString(nameType), typeToString(parentType));
4686
- }
4687
- return anyType;
4688
- }
4689
- const declaredType = getConstraintForLocation(getTypeOfPropertyOfType(parentType, text), declaration.name);
4690
- type = declaredType && getFlowTypeOfReference(declaration, declaredType) ||
4691
- isNumericLiteralName(text) && getIndexTypeOfType(parentType, IndexKind.Number) ||
4692
- getIndexTypeOfType(parentType, IndexKind.String);
4693
- if (!type) {
4694
- error(name, Diagnostics.Type_0_has_no_property_1_and_no_string_index_signature, typeToString(parentType), declarationNameToString(name));
4695
- return errorType;
4696
- }
4654
+ const exprType = isComputedPropertyName(name)
4655
+ ? checkComputedPropertyName(name)
4656
+ : isIdentifier(name)
4657
+ ? getLiteralType(unescapeLeadingUnderscores(name.escapedText))
4658
+ : checkExpression(name);
4659
+ const declaredType = checkIndexedAccessIndexType(getIndexedAccessType(getApparentType(parentType), exprType, name), name);
4660
+ type = getFlowTypeOfReference(declaration, getConstraintForLocation(declaredType, declaration.name));
4697
4661
}
4698
4662
}
4699
4663
else {
@@ -9360,12 +9324,16 @@ namespace ts {
9360
9324
return false;
9361
9325
}
9362
9326
9363
- function getPropertyTypeForIndexType(objectType: Type, indexType: Type, accessNode: ElementAccessExpression | IndexedAccessTypeNode | undefined, cacheSymbol: boolean, missingType: Type) {
9327
+ function getPropertyTypeForIndexType(objectType: Type, indexType: Type, accessNode: ElementAccessExpression | IndexedAccessTypeNode | PropertyName | undefined, cacheSymbol: boolean, missingType: Type) {
9364
9328
const accessExpression = accessNode && accessNode.kind === SyntaxKind.ElementAccessExpression ? accessNode : undefined;
9365
- const propName = isTypeUsableAsLateBoundName(indexType) ? getLateBoundNameFromType(indexType) :
9366
- accessExpression && checkThatExpressionIsProperSymbolReference(accessExpression.argumentExpression, indexType, /*reportError*/ false) ?
9367
- getPropertyNameForKnownSymbolName(idText((<PropertyAccessExpression>accessExpression.argumentExpression).name)) :
9368
- undefined;
9329
+ const propName = isTypeUsableAsLateBoundName(indexType)
9330
+ ? getLateBoundNameFromType(indexType)
9331
+ : accessExpression && checkThatExpressionIsProperSymbolReference(accessExpression.argumentExpression, indexType, /*reportError*/ false)
9332
+ ? getPropertyNameForKnownSymbolName(idText((<PropertyAccessExpression>accessExpression.argumentExpression).name))
9333
+ : accessNode && isPropertyName(accessNode)
9334
+ // late bound names are handled in the first branch, so here we only need to handle normal names
9335
+ ? getPropertyNameForPropertyNameNode(accessNode)
9336
+ : undefined;
9369
9337
if (propName !== undefined) {
9370
9338
const prop = getPropertyOfType(objectType, propName);
9371
9339
if (prop) {
@@ -9386,7 +9354,7 @@ namespace ts {
9386
9354
}
9387
9355
if (everyType(objectType, isTupleType) && isNumericLiteralName(propName) && +propName >= 0) {
9388
9356
if (accessNode && everyType(objectType, t => !(<TupleTypeReference>t).target.hasRestElement)) {
9389
- const indexNode = accessNode.kind === SyntaxKind.ElementAccessExpression ? accessNode.argumentExpression : accessNode.indexType ;
9357
+ const indexNode = getIndexNodeForAccessExpression( accessNode) ;
9390
9358
error(indexNode, Diagnostics.Property_0_does_not_exist_on_type_1, unescapeLeadingUnderscores(propName), typeToString(objectType));
9391
9359
}
9392
9360
return mapType(objectType, t => getRestTypeOfTupleType(<TupleTypeReference>t) || undefinedType);
@@ -9401,7 +9369,7 @@ namespace ts {
9401
9369
undefined;
9402
9370
if (indexInfo) {
9403
9371
if (accessNode && !isTypeAssignableToKind(indexType, TypeFlags.String | TypeFlags.Number)) {
9404
- const indexNode = accessNode.kind === SyntaxKind.ElementAccessExpression ? accessNode.argumentExpression : accessNode.indexType ;
9372
+ const indexNode = getIndexNodeForAccessExpression( accessNode) ;
9405
9373
error(indexNode, Diagnostics.Type_0_cannot_be_used_as_an_index_type, typeToString(indexType));
9406
9374
}
9407
9375
else if (accessExpression && indexInfo.isReadonly && (isAssignmentTarget(accessExpression) || isDeleteTarget(accessExpression))) {
@@ -9442,7 +9410,7 @@ namespace ts {
9442
9410
return anyType;
9443
9411
}
9444
9412
if (accessNode) {
9445
- const indexNode = accessNode.kind === SyntaxKind.ElementAccessExpression ? accessNode.argumentExpression : accessNode.indexType ;
9413
+ const indexNode = getIndexNodeForAccessExpression( accessNode) ;
9446
9414
if (indexType.flags & (TypeFlags.StringLiteral | TypeFlags.NumberLiteral)) {
9447
9415
error(indexNode, Diagnostics.Property_0_does_not_exist_on_type_1, "" + (<LiteralType>indexType).value, typeToString(objectType));
9448
9416
}
@@ -9459,6 +9427,16 @@ namespace ts {
9459
9427
return missingType;
9460
9428
}
9461
9429
9430
+ function getIndexNodeForAccessExpression(accessNode: ElementAccessExpression | IndexedAccessTypeNode | PropertyName) {
9431
+ return accessNode.kind === SyntaxKind.ElementAccessExpression
9432
+ ? accessNode.argumentExpression
9433
+ : accessNode.kind === SyntaxKind.IndexedAccessType
9434
+ ? accessNode.indexType
9435
+ : accessNode.kind === SyntaxKind.ComputedPropertyName
9436
+ ? accessNode.expression
9437
+ : accessNode;
9438
+ }
9439
+
9462
9440
function isGenericObjectType(type: Type): boolean {
9463
9441
return maybeTypeOfKind(type, TypeFlags.InstantiableNonPrimitive | TypeFlags.GenericMappedType);
9464
9442
}
@@ -9522,7 +9500,7 @@ namespace ts {
9522
9500
return instantiateType(getTemplateTypeFromMappedType(objectType), templateMapper);
9523
9501
}
9524
9502
9525
- function getIndexedAccessType(objectType: Type, indexType: Type, accessNode?: ElementAccessExpression | IndexedAccessTypeNode, missingType = accessNode ? errorType : unknownType): Type {
9503
+ function getIndexedAccessType(objectType: Type, indexType: Type, accessNode?: ElementAccessExpression | IndexedAccessTypeNode | PropertyName , missingType = accessNode ? errorType : unknownType): Type {
9526
9504
if (objectType === wildcardType || indexType === wildcardType) {
9527
9505
return wildcardType;
9528
9506
}
@@ -23208,7 +23186,7 @@ namespace ts {
23208
23186
forEach(node.types, checkSourceElement);
23209
23187
}
23210
23188
23211
- function checkIndexedAccessIndexType(type: Type, accessNode: ElementAccessExpression | IndexedAccessTypeNode ) {
23189
+ function checkIndexedAccessIndexType(type: Type, accessNode: Node ) {
23212
23190
if (!(type.flags & TypeFlags.IndexedAccess)) {
23213
23191
return type;
23214
23192
}
0 commit comments