@@ -7195,8 +7195,7 @@ namespace ts {
7195
7195
return type;
7196
7196
}
7197
7197
if (type.flags & TypeFlags.Index) {
7198
- const keys = getIndexType(getApparentType((<IndexType>type).type));
7199
- return isIndexType ? filterType(keys, t => !!(t.flags & TypeFlags.Literal)) : keys;
7198
+ return getIndexType(getApparentType((<IndexType>type).type));
7200
7199
}
7201
7200
if (type.flags & TypeFlags.Conditional) {
7202
7201
if ((<ConditionalType>type).root.isDistributive) {
@@ -7491,8 +7490,8 @@ namespace ts {
7491
7490
function getConstraintFromIndexedAccess(type: IndexedAccessType) {
7492
7491
const objectType = getConstraintOfType(type.objectType) || type.objectType;
7493
7492
if (objectType !== type.objectType) {
7494
- const constraint = getIndexedAccessType (objectType, type.indexType, /*accessNode*/ undefined, errorType );
7495
- if (constraint && constraint !== errorType ) {
7493
+ const constraint = getIndexedAccessTypeOrUndefined (objectType, type.indexType);
7494
+ if (constraint) {
7496
7495
return constraint;
7497
7496
}
7498
7497
}
@@ -7686,8 +7685,8 @@ namespace ts {
7686
7685
if (t.flags & TypeFlags.IndexedAccess) {
7687
7686
const baseObjectType = getBaseConstraint((<IndexedAccessType>t).objectType);
7688
7687
const baseIndexType = getBaseConstraint((<IndexedAccessType>t).indexType);
7689
- const baseIndexedAccess = baseObjectType && baseIndexType ? getIndexedAccessType (baseObjectType, baseIndexType, /*accessNode*/ undefined, errorType) : undefined ;
7690
- return baseIndexedAccess && baseIndexedAccess !== errorType ? getBaseConstraint(baseIndexedAccess) : undefined ;
7688
+ const baseIndexedAccess = baseObjectType && baseIndexType && getIndexedAccessTypeOrUndefined (baseObjectType, baseIndexType) ;
7689
+ return baseIndexedAccess && getBaseConstraint(baseIndexedAccess);
7691
7690
}
7692
7691
if (t.flags & TypeFlags.Conditional) {
7693
7692
const constraint = getConstraintFromConditionalType(<ConditionalType>t);
@@ -9875,7 +9874,7 @@ namespace ts {
9875
9874
return false;
9876
9875
}
9877
9876
9878
- function getPropertyTypeForIndexType(originalObjectType: Type, objectType: Type, indexType: Type, accessNode: ElementAccessExpression | IndexedAccessTypeNode | PropertyName | BindingName | SyntheticExpression | undefined, cacheSymbol: boolean, missingType: Type ) {
9877
+ function getPropertyTypeForIndexType(originalObjectType: Type, objectType: Type, indexType: Type, accessNode: ElementAccessExpression | IndexedAccessTypeNode | PropertyName | BindingName | SyntheticExpression | undefined, cacheSymbol: boolean) {
9879
9878
const accessExpression = accessNode && accessNode.kind === SyntaxKind.ElementAccessExpression ? accessNode : undefined;
9880
9879
const propName = isTypeUsableAsPropertyName(indexType) ?
9881
9880
getPropertyNameFromType(indexType) :
@@ -9892,7 +9891,7 @@ namespace ts {
9892
9891
markPropertyAsReferenced(prop, accessExpression, /*isThisAccess*/ accessExpression.expression.kind === SyntaxKind.ThisKeyword);
9893
9892
if (isAssignmentTarget(accessExpression) && (isReferenceToReadonlyEntity(accessExpression, prop) || isReferenceThroughNamespaceImport(accessExpression))) {
9894
9893
error(accessExpression.argumentExpression, Diagnostics.Cannot_assign_to_0_because_it_is_a_read_only_property, symbolToString(prop));
9895
- return missingType ;
9894
+ return undefined ;
9896
9895
}
9897
9896
if (cacheSymbol) {
9898
9897
getNodeLinks(accessNode!).resolvedSymbol = prop;
@@ -9921,16 +9920,19 @@ namespace ts {
9921
9920
if (objectType.flags & (TypeFlags.Any | TypeFlags.Never)) {
9922
9921
return objectType;
9923
9922
}
9924
- const indexInfo = accessExpression && isAssignmentTarget(accessExpression) && isGenericObjectType(originalObjectType) ? undefined :
9925
- isTypeAssignableToKind(indexType, TypeFlags.NumberLike) && getIndexInfoOfType(objectType, IndexKind.Number) ||
9926
- getIndexInfoOfType(objectType, IndexKind.String) ||
9927
- undefined;
9923
+ const isAssignment = accessExpression && (isAssignmentTarget(accessExpression) || isDeleteTarget(accessExpression));
9924
+ if (isAssignment && maybeTypeOfKind(originalObjectType, TypeFlags.Instantiable)) {
9925
+ error(accessExpression, Diagnostics.Type_0_cannot_be_indexed_by_type_1, typeToString(originalObjectType), typeToString(indexType));
9926
+ return undefined;
9927
+ }
9928
+ const indexInfo = isTypeAssignableToKind(indexType, TypeFlags.NumberLike) && getIndexInfoOfType(objectType, IndexKind.Number) ||
9929
+ getIndexInfoOfType(objectType, IndexKind.String);
9928
9930
if (indexInfo) {
9929
9931
if (accessNode && !isTypeAssignableToKind(indexType, TypeFlags.String | TypeFlags.Number)) {
9930
9932
const indexNode = getIndexNodeForAccessExpression(accessNode);
9931
9933
error(indexNode, Diagnostics.Type_0_cannot_be_used_as_an_index_type, typeToString(indexType));
9932
9934
}
9933
- else if (accessExpression && indexInfo.isReadonly && (isAssignmentTarget(accessExpression) || isDeleteTarget(accessExpression)) ) {
9935
+ else if (isAssignment && indexInfo.isReadonly) {
9934
9936
error(accessExpression, Diagnostics.Index_signature_in_type_0_only_permits_reading, typeToString(objectType));
9935
9937
}
9936
9938
return indexInfo.type;
@@ -9964,7 +9966,7 @@ namespace ts {
9964
9966
}
9965
9967
}
9966
9968
}
9967
- return missingType ;
9969
+ return undefined ;
9968
9970
}
9969
9971
}
9970
9972
if (isJSLiteralType(objectType)) {
@@ -9985,7 +9987,7 @@ namespace ts {
9985
9987
if (isTypeAny(indexType)) {
9986
9988
return indexType;
9987
9989
}
9988
- return missingType ;
9990
+ return undefined ;
9989
9991
}
9990
9992
9991
9993
function getIndexNodeForAccessExpression(accessNode: ElementAccessExpression | IndexedAccessTypeNode | PropertyName | BindingName | SyntheticExpression) {
@@ -10076,7 +10078,11 @@ namespace ts {
10076
10078
return instantiateType(getTemplateTypeFromMappedType(objectType), templateMapper);
10077
10079
}
10078
10080
10079
- function getIndexedAccessType(objectType: Type, indexType: Type, accessNode?: ElementAccessExpression | IndexedAccessTypeNode | PropertyName | BindingName | SyntheticExpression, missingType = accessNode ? errorType : unknownType): Type {
10081
+ function getIndexedAccessType(objectType: Type, indexType: Type, accessNode?: ElementAccessExpression | IndexedAccessTypeNode | PropertyName | BindingName | SyntheticExpression, writing?: boolean): Type {
10082
+ return getIndexedAccessTypeOrUndefined(objectType, indexType, accessNode, writing) || (accessNode ? errorType : unknownType);
10083
+ }
10084
+
10085
+ function getIndexedAccessTypeOrUndefined(objectType: Type, indexType: Type, accessNode?: ElementAccessExpression | IndexedAccessTypeNode | PropertyName | BindingName | SyntheticExpression, writing?: boolean): Type | undefined {
10080
10086
if (objectType === wildcardType || indexType === wildcardType) {
10081
10087
return wildcardType;
10082
10088
}
@@ -10105,25 +10111,25 @@ namespace ts {
10105
10111
const propTypes: Type[] = [];
10106
10112
let wasMissingProp = false;
10107
10113
for (const t of (<UnionType>indexType).types) {
10108
- const propType = getPropertyTypeForIndexType(objectType, apparentObjectType, t, accessNode, /*cacheSymbol*/ false, missingType);
10109
- if (propType === missingType) {
10110
- if (!accessNode) {
10111
- // If there's no error node, we can immeditely stop, since error reporting is off
10112
- return missingType;
10113
- }
10114
- else {
10115
- // Otherwise we set a flag and return at the end of the loop so we still mark all errors
10116
- wasMissingProp = true;
10117
- }
10114
+ const propType = getPropertyTypeForIndexType(objectType, apparentObjectType, t, accessNode, /*cacheSymbol*/ false);
10115
+ if (propType) {
10116
+ propTypes.push(propType);
10117
+ }
10118
+ else if (!accessNode) {
10119
+ // If there's no error node, we can immeditely stop, since error reporting is off
10120
+ return undefined;
10121
+ }
10122
+ else {
10123
+ // Otherwise we set a flag and return at the end of the loop so we still mark all errors
10124
+ wasMissingProp = true;
10118
10125
}
10119
- propTypes.push(propType);
10120
10126
}
10121
10127
if (wasMissingProp) {
10122
- return missingType ;
10128
+ return undefined ;
10123
10129
}
10124
- return !accessNode || getAssignmentTargetKind(accessNode) === AssignmentKind.None ? getUnionType (propTypes) : getIntersectionType (propTypes);
10130
+ return writing ? getIntersectionType (propTypes) : getUnionType (propTypes);
10125
10131
}
10126
- return getPropertyTypeForIndexType(objectType, apparentObjectType, indexType, accessNode, /*cacheSymbol*/ true, missingType );
10132
+ return getPropertyTypeForIndexType(objectType, apparentObjectType, indexType, accessNode, /*cacheSymbol*/ true);
10127
10133
}
10128
10134
10129
10135
function getTypeFromIndexedAccessTypeNode(node: IndexedAccessTypeNode) {
@@ -11512,10 +11518,10 @@ namespace ts {
11512
11518
let reportedError = false;
11513
11519
for (let status = iterator.next(); !status.done; status = iterator.next()) {
11514
11520
const { errorNode: prop, innerExpression: next, nameType, errorMessage } = status.value;
11515
- const targetPropType = getIndexedAccessType (target, nameType, /*accessNode*/ undefined, errorType );
11516
- if (targetPropType === errorType || targetPropType.flags & TypeFlags.IndexedAccess) continue; // Don't elaborate on indexes on generic variables
11517
- const sourcePropType = getIndexedAccessType (source, nameType, /*accessNode*/ undefined, errorType );
11518
- if (sourcePropType !== errorType && targetPropType !== errorType && !checkTypeRelatedTo(sourcePropType, targetPropType, relation, /*errorNode*/ undefined)) {
11521
+ const targetPropType = getIndexedAccessTypeOrUndefined (target, nameType);
11522
+ if (! targetPropType || targetPropType.flags & TypeFlags.IndexedAccess) continue; // Don't elaborate on indexes on generic variables
11523
+ const sourcePropType = getIndexedAccessTypeOrUndefined (source, nameType);
11524
+ if (sourcePropType && !checkTypeRelatedTo(sourcePropType, targetPropType, relation, /*errorNode*/ undefined)) {
11519
11525
const elaborated = next && elaborateError(next, sourcePropType, targetPropType, relation, /*headMessage*/ undefined);
11520
11526
if (elaborated) {
11521
11527
reportedError = true;
@@ -12819,9 +12825,7 @@ namespace ts {
12819
12825
if (indexType.flags & TypeFlags.StructuredOrInstantiable) {
12820
12826
const keyType = getLowerBoundOfKeyType(indexType, /*isIndexType*/ true);
12821
12827
if (keyType !== indexType && !(keyType.flags & TypeFlags.Never)) {
12822
- const targetType = keyType.flags & TypeFlags.Union ?
12823
- getIntersectionType(map((<UnionType>keyType).types, t => getIndexedAccessType(objectType, t))) :
12824
- getIndexedAccessType(objectType, keyType);
12828
+ const targetType = getIndexedAccessType(objectType, keyType, /*accessNode*/ undefined, /*writing*/ true);
12825
12829
if (result = isRelatedTo(source, targetType, reportErrors)) {
12826
12830
return result;
12827
12831
}
@@ -12830,7 +12834,8 @@ namespace ts {
12830
12834
else {
12831
12835
const constraint = getConstraintOfType(objectType);
12832
12836
if (constraint) {
12833
- if (result = isRelatedTo(source, getIndexedAccessType(constraint, indexType), reportErrors)) {
12837
+ const targetType = getIndexedAccessType(constraint, indexType, /*accessNode*/ undefined, /*writing*/ true);
12838
+ if (result = isRelatedTo(source, targetType, reportErrors)) {
12834
12839
return result;
12835
12840
}
12836
12841
}
@@ -19975,7 +19980,9 @@ namespace ts {
19975
19980
return errorType;
19976
19981
}
19977
19982
19978
- return checkIndexedAccessIndexType(getIndexedAccessType(objectType, isForInVariableForNumericPropertyNames(indexExpression) ? numberType : indexType, node), node);
19983
+ const effectiveIndexType = isForInVariableForNumericPropertyNames(indexExpression) ? numberType : indexType;
19984
+ const indexedAccessType = getIndexedAccessType(objectType, effectiveIndexType, node, isAssignmentTarget(node));
19985
+ return checkIndexedAccessIndexType(indexedAccessType, node);
19979
19986
}
19980
19987
19981
19988
function checkThatExpressionIsProperSymbolReference(expression: Expression, expressionType: Type, reportError: boolean): boolean {
@@ -24570,7 +24577,7 @@ namespace ts {
24570
24577
return type;
24571
24578
}
24572
24579
error(accessNode, Diagnostics.Type_0_cannot_be_used_to_index_type_1, typeToString(indexType), typeToString(objectType));
24573
- return type ;
24580
+ return errorType ;
24574
24581
}
24575
24582
24576
24583
function checkIndexedAccessType(node: IndexedAccessTypeNode) {
0 commit comments