@@ -5900,6 +5900,10 @@ namespace ts {
5900
5900
}
5901
5901
5902
5902
function getConstraintOfIndexedAccess(type: IndexedAccessType) {
5903
+ const transformed = getTransformedIndexedAccessType(type);
5904
+ if (transformed) {
5905
+ return transformed;
5906
+ }
5903
5907
const baseObjectType = getBaseConstraintOfType(type.objectType);
5904
5908
const baseIndexType = getBaseConstraintOfType(type.indexType);
5905
5909
return baseObjectType || baseIndexType ? getIndexedAccessType(baseObjectType || type.objectType, baseIndexType || type.indexType) : undefined;
@@ -5971,11 +5975,18 @@ namespace ts {
5971
5975
return stringType;
5972
5976
}
5973
5977
if (t.flags & TypeFlags.IndexedAccess) {
5978
+ const transformed = getTransformedIndexedAccessType(<IndexedAccessType>t);
5979
+ if (transformed) {
5980
+ return getBaseConstraint(transformed);
5981
+ }
5974
5982
const baseObjectType = getBaseConstraint((<IndexedAccessType>t).objectType);
5975
5983
const baseIndexType = getBaseConstraint((<IndexedAccessType>t).indexType);
5976
5984
const baseIndexedAccess = baseObjectType && baseIndexType ? getIndexedAccessType(baseObjectType, baseIndexType) : undefined;
5977
5985
return baseIndexedAccess && baseIndexedAccess !== unknownType ? getBaseConstraint(baseIndexedAccess) : undefined;
5978
5986
}
5987
+ if (isGenericMappedType(t)) {
5988
+ return emptyObjectType;
5989
+ }
5979
5990
return t;
5980
5991
}
5981
5992
}
@@ -7610,7 +7621,44 @@ namespace ts {
7610
7621
false;
7611
7622
}
7612
7623
7613
- function getIndexedAccessType(objectType: Type, indexType: Type, accessNode?: ElementAccessExpression | IndexedAccessTypeNode) {
7624
+ // Return true if the given type is a non-generic object type with a string index signature and no
7625
+ // other members.
7626
+ function isStringIndexOnlyType(type: Type) {
7627
+ if (type.flags & TypeFlags.Object && !isGenericMappedType(type)) {
7628
+ const t = resolveStructuredTypeMembers(<ObjectType>type);
7629
+ return t.properties.length === 0 &&
7630
+ t.callSignatures.length === 0 && t.constructSignatures.length === 0 &&
7631
+ t.stringIndexInfo && !t.numberIndexInfo;
7632
+ }
7633
+ return false;
7634
+ }
7635
+
7636
+ // Given an indexed access type T[K], if T is an intersection containing one or more generic types and one or
7637
+ // more object types with only a string index signature, e.g. '(U & V & { [x: string]: D })[K]', return a
7638
+ // transformed type of the form '(U & V)[K] | D'. This allows us to properly reason about higher order indexed
7639
+ // access types with default property values as expressed by D.
7640
+ function getTransformedIndexedAccessType(type: IndexedAccessType): Type {
7641
+ const objectType = type.objectType;
7642
+ if (objectType.flags & TypeFlags.Intersection && isGenericObjectType(objectType) && some((<IntersectionType>objectType).types, isStringIndexOnlyType)) {
7643
+ const regularTypes: Type[] = [];
7644
+ const stringIndexTypes: Type[] = [];
7645
+ for (const t of (<IntersectionType>objectType).types) {
7646
+ if (isStringIndexOnlyType(t)) {
7647
+ stringIndexTypes.push(getIndexTypeOfType(t, IndexKind.String));
7648
+ }
7649
+ else {
7650
+ regularTypes.push(t);
7651
+ }
7652
+ }
7653
+ return getUnionType([
7654
+ getIndexedAccessType(getIntersectionType(regularTypes), type.indexType),
7655
+ getIntersectionType(stringIndexTypes)
7656
+ ]);
7657
+ }
7658
+ return undefined;
7659
+ }
7660
+
7661
+ function getIndexedAccessType(objectType: Type, indexType: Type, accessNode?: ElementAccessExpression | IndexedAccessTypeNode): Type {
7614
7662
// If the object type is a mapped type { [P in K]: E }, where K is generic, we instantiate E using a mapper
7615
7663
// that substitutes the index type for P. For example, for an index access { [P in K]: Box<T[P]> }[X], we
7616
7664
// construct the type Box<T[X]>.
@@ -18662,6 +18710,8 @@ namespace ts {
18662
18710
}
18663
18711
18664
18712
function checkIndexedAccessType(node: IndexedAccessTypeNode) {
18713
+ checkSourceElement(node.objectType);
18714
+ checkSourceElement(node.indexType);
18665
18715
checkIndexedAccessIndexType(getTypeFromIndexedAccessTypeNode(node), node);
18666
18716
}
18667
18717
0 commit comments