Cache simplified indexed accesses to better handle circularly constrained indexed acceses (#24072)

This commit is contained in:
Wesley Wigham
2018-05-14 12:54:26 -07:00
committed by GitHub
parent 7e3af08a09
commit ba4bf21ead
8 changed files with 53 additions and 5 deletions

View File

@@ -8692,6 +8692,10 @@ namespace ts {
// Transform an indexed access to a simpler form, if possible. Return the simpler form, or return
// the type itself if no transformation is possible.
function getSimplifiedIndexedAccessType(type: IndexedAccessType): Type {
if (type.simplified) {
return type.simplified === circularConstraintType ? type : type.simplified;
}
type.simplified = circularConstraintType;
const objectType = type.objectType;
if (objectType.flags & TypeFlags.Intersection && isGenericObjectType(objectType)) {
// Given an indexed access type T[K], if T is an intersection containing one or more generic types and one or
@@ -8709,7 +8713,7 @@ namespace ts {
regularTypes.push(t);
}
}
return getUnionType([
return type.simplified = getUnionType([
getSimplifiedType(getIndexedAccessType(getIntersectionType(regularTypes), type.indexType)),
getIntersectionType(stringIndexTypes)
]);
@@ -8720,7 +8724,7 @@ namespace ts {
// eventually anyway, but it easier to reason about.
if (some((<IntersectionType>objectType).types, isMappedTypeToNever)) {
const nonNeverTypes = filter((<IntersectionType>objectType).types, t => !isMappedTypeToNever(t));
return getSimplifiedType(getIndexedAccessType(getIntersectionType(nonNeverTypes), type.indexType));
return type.simplified = getSimplifiedType(getIndexedAccessType(getIntersectionType(nonNeverTypes), type.indexType));
}
}
// If the object type is a mapped type { [P in K]: E }, where K is generic, instantiate E using a mapper
@@ -8728,15 +8732,15 @@ namespace ts {
// construct the type Box<T[X]>. We do not further simplify the result because mapped types can be recursive
// and we might never terminate.
if (isGenericMappedType(objectType)) {
return substituteIndexedMappedType(objectType, type);
return type.simplified = substituteIndexedMappedType(objectType, type);
}
if (objectType.flags & TypeFlags.TypeParameter) {
const constraint = getConstraintFromTypeParameter(objectType as TypeParameter);
if (constraint && isGenericMappedType(constraint)) {
return substituteIndexedMappedType(constraint, type);
return type.simplified = substituteIndexedMappedType(constraint, type);
}
}
return type;
return type.simplified = type;
}
function substituteIndexedMappedType(objectType: MappedType, type: IndexedAccessType) {

View File

@@ -3973,6 +3973,7 @@ namespace ts {
objectType: Type;
indexType: Type;
constraint?: Type;
simplified?: Type;
}
export type TypeVariable = TypeParameter | IndexedAccessType;