Skip to content

Commit ece1f19

Browse files
committed
Refactor getIndexedAccessType to be reusable from checkIndexedAccess
1 parent 4b50ef3 commit ece1f19

File tree

1 file changed

+52
-35
lines changed

1 file changed

+52
-35
lines changed

src/compiler/checker.ts

Lines changed: 52 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -5697,63 +5697,80 @@ namespace ts {
56975697
return links.resolvedType;
56985698
}
56995699

5700-
function createIndexedAccessType(objectType: Type, keyType: TypeParameter) {
5700+
function createIndexedAccessType(objectType: Type, indexType: TypeParameter) {
57015701
const type = <IndexedAccessType>createType(TypeFlags.IndexedAccess);
57025702
type.objectType = objectType;
5703-
type.indexType = keyType;
5703+
type.indexType = indexType;
57045704
return type;
57055705
}
57065706

5707-
function getIndexedAccessTypeForTypeParameter(objectType: Type, keyType: TypeParameter) {
5708-
const indexedAccessTypes = keyType.resolvedIndexedAccessTypes || (keyType.resolvedIndexedAccessTypes = []);
5709-
return indexedAccessTypes[objectType.id] || (indexedAccessTypes[objectType.id] = createIndexedAccessType(objectType, keyType));
5707+
function getIndexedAccessTypeForTypeParameter(objectType: Type, indexType: TypeParameter) {
5708+
const indexedAccessTypes = indexType.resolvedIndexedAccessTypes || (indexType.resolvedIndexedAccessTypes = []);
5709+
return indexedAccessTypes[objectType.id] || (indexedAccessTypes[objectType.id] = createIndexedAccessType(objectType, indexType));
57105710
}
57115711

5712-
function getPropertyTypeForIndexType(objectType: Type, indexType: Type) {
5713-
return indexType.flags & (TypeFlags.StringLiteral | TypeFlags.NumberLiteral | TypeFlags.EnumLiteral) && getTypeOfPropertyOfType(objectType, escapeIdentifier((<LiteralType>indexType).text)) ||
5714-
isTypeAnyOrAllConstituentTypesHaveKind(indexType, TypeFlags.NumberLike) && getIndexTypeOfType(objectType, IndexKind.Number) ||
5715-
isTypeAnyOrAllConstituentTypesHaveKind(indexType, TypeFlags.StringLike | TypeFlags.NumberLike) && getIndexTypeOfType(objectType, IndexKind.String) ||
5716-
undefined;
5717-
}
5718-
5719-
function getIndexedAccessType(objectType: Type, keyType: Type) {
5720-
return keyType.flags & TypeFlags.Any ? anyType :
5721-
keyType.flags & TypeFlags.TypeParameter ? getIndexedAccessTypeForTypeParameter(objectType, <TypeParameter>keyType) :
5722-
mapType(keyType, t => getPropertyTypeForIndexType(objectType, t) || unknownType);
5712+
function getPropertyTypeForIndexType(objectType: Type, indexType: Type, errorNode?: Node) {
5713+
if (indexType.flags & (TypeFlags.StringLiteral | TypeFlags.NumberLiteral | TypeFlags.EnumLiteral)) {
5714+
const propType = getTypeOfPropertyOfType(objectType, escapeIdentifier((<LiteralType>indexType).text));
5715+
if (propType) {
5716+
return propType;
5717+
}
5718+
}
5719+
if (isTypeAnyOrAllConstituentTypesHaveKind(indexType, TypeFlags.NumberLike)) {
5720+
const numberIndexType = getIndexTypeOfType(objectType, IndexKind.Number);
5721+
if (numberIndexType) {
5722+
return numberIndexType;
5723+
}
5724+
}
5725+
if (isTypeAnyOrAllConstituentTypesHaveKind(indexType, TypeFlags.StringLike | TypeFlags.NumberLike)) {
5726+
const stringIndexType = getIndexTypeOfType(objectType, IndexKind.String);
5727+
if (stringIndexType) {
5728+
return stringIndexType;
5729+
}
5730+
}
5731+
if (errorNode) {
5732+
if (indexType.flags & (TypeFlags.StringLiteral | TypeFlags.NumberLiteral)) {
5733+
error(errorNode, Diagnostics.Property_0_does_not_exist_on_type_1, (<LiteralType>indexType).text, typeToString(objectType));
5734+
}
5735+
else if (indexType.flags & (TypeFlags.String | TypeFlags.Number)) {
5736+
error(errorNode, Diagnostics.Type_0_has_no_matching_index_signature_for_type_1, typeToString(objectType), typeToString(indexType));
5737+
}
5738+
else {
5739+
error(errorNode, Diagnostics.Type_0_cannot_be_used_as_an_index_type, typeToString(indexType));
5740+
}
5741+
}
5742+
return unknownType;
57235743
}
57245744

5725-
function resolveIndexedAccessTypeNode(node: IndexedAccessTypeNode) {
5726-
const objectType = getTypeFromTypeNodeNoAlias(node.objectType);
5727-
const indexType = getTypeFromTypeNodeNoAlias(node.indexType);
5745+
function getIndexedAccessType(objectType: Type, indexType: Type, errorNode?: Node) {
57285746
if (indexType.flags & TypeFlags.TypeParameter) {
57295747
if (!isTypeAssignableTo(getConstraintOfTypeParameter(<TypeParameter>indexType), getIndexType(objectType))) {
5730-
error(node.indexType, Diagnostics.Type_0_is_not_constrained_to_keyof_1, typeToString(indexType), typeToString(objectType));
5748+
if (errorNode) {
5749+
error(errorNode, Diagnostics.Type_0_is_not_constrained_to_keyof_1, typeToString(indexType), typeToString(objectType));
5750+
}
57315751
return unknownType;
57325752
}
5733-
return getIndexedAccessType(objectType, indexType);
5753+
return getIndexedAccessTypeForTypeParameter(objectType, <TypeParameter>indexType);
57345754
}
5735-
const indexTypes = indexType.flags & TypeFlags.Union && !(indexType.flags & TypeFlags.Primitive) ? (<UnionType>indexType).types : [indexType];
5736-
for (const t of indexTypes) {
5737-
if (!getPropertyTypeForIndexType(objectType, t)) {
5738-
if (t.flags & (TypeFlags.StringLiteral | TypeFlags.NumberLiteral)) {
5739-
error(node.indexType, Diagnostics.Property_0_does_not_exist_on_type_1, (<LiteralType>t).text, typeToString(objectType))
5740-
}
5741-
else if (t.flags & (TypeFlags.String | TypeFlags.Number)) {
5742-
error(node.indexType, Diagnostics.Type_0_has_no_matching_index_signature_for_type_1, typeToString(objectType), typeToString(t));
5743-
}
5744-
else {
5745-
error(node.indexType, Diagnostics.Type_0_cannot_be_used_as_an_index_type, typeToString(t));
5755+
if (indexType.flags & TypeFlags.Union && !(indexType.flags & TypeFlags.Primitive)) {
5756+
const propTypes: Type[] = [];
5757+
for (const t of (<UnionType>indexType).types) {
5758+
const propType = getPropertyTypeForIndexType(objectType, t, errorNode);
5759+
if (propType === unknownType) {
5760+
return unknownType;
57465761
}
5747-
return unknownType;
5762+
propTypes.push(propType);
57485763
}
5764+
return getUnionType(propTypes);
57495765
}
5750-
return getIndexedAccessType(objectType, indexType);
5766+
return getPropertyTypeForIndexType(objectType, indexType, errorNode);
57515767
}
57525768

57535769
function getTypeFromIndexedAccessTypeNode(node: IndexedAccessTypeNode) {
57545770
const links = getNodeLinks(node);
57555771
if (!links.resolvedType) {
5756-
links.resolvedType = resolveIndexedAccessTypeNode(node);
5772+
links.resolvedType = getIndexedAccessType(getTypeFromTypeNodeNoAlias(node.objectType),
5773+
getTypeFromTypeNodeNoAlias(node.indexType), node.indexType);
57575774
}
57585775
return links.resolvedType;
57595776
}

0 commit comments

Comments
 (0)