Infer into recursive mapped type targets (#53647)

This commit is contained in:
Mateusz Burzyński
2023-07-06 22:46:46 +02:00
committed by GitHub
parent a05699c9b9
commit bd61cbb1f3
6 changed files with 195 additions and 19 deletions

View File

@@ -2068,7 +2068,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
/** Key is "/path/to/a.ts|/path/to/b.ts". */
var amalgamatedDuplicates: Map<string, DuplicateInfoForFiles> | undefined;
var reverseMappedCache = new Map<string, Type | undefined>();
var inInferTypeForHomomorphicMappedType = false;
var homomorphicMappedTypeInferenceStack: string[] = [];
var ambientModulesCache: Symbol[] | undefined;
/**
* List of every ambient module with a "*" wildcard.
@@ -24126,17 +24126,18 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
* variable T[P] (i.e. we treat the type T[P] as the type variable we're inferring for).
*/
function inferTypeForHomomorphicMappedType(source: Type, target: MappedType, constraint: IndexType): Type | undefined {
if (inInferTypeForHomomorphicMappedType) {
const cacheKey = source.id + "," + target.id + "," + constraint.id;
if (reverseMappedCache.has(cacheKey)) {
return reverseMappedCache.get(cacheKey);
}
const recursionKey = source.id + "," + (target.target || target).id;
if (contains(homomorphicMappedTypeInferenceStack, recursionKey)) {
return undefined;
}
const key = source.id + "," + target.id + "," + constraint.id;
if (reverseMappedCache.has(key)) {
return reverseMappedCache.get(key);
}
inInferTypeForHomomorphicMappedType = true;
homomorphicMappedTypeInferenceStack.push(recursionKey);
const type = createReverseMappedType(source, target, constraint);
inInferTypeForHomomorphicMappedType = false;
reverseMappedCache.set(key, type);
homomorphicMappedTypeInferenceStack.pop();
reverseMappedCache.set(cacheKey, type);
return type;
}