Cut off inference for recursive mapped types
Previously, when inferring to a self-referential (or otherwise recursive) homomorphic mapped type from a source type that also has recursive references, type inference would enter infinite recursion. Now there is a more complex stack for mapped type inference. It mirrors the existing symbolStack but (1) includes the source type and (2) is passed through inferTypeForHomomorphicMappedType, which is actually called outside of inferTypes, and so restarts the symbolStack cache every time.
This commit is contained in:
parent
5ee640d2b6
commit
b1316e589e
|
@ -11127,7 +11127,7 @@ namespace ts {
|
|||
* property is computed by inferring from the source property type to X for the type
|
||||
* 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): Type {
|
||||
function inferTypeForHomomorphicMappedType(source: Type, target: MappedType, mappedTypeStack: [Type, Symbol][]): Type {
|
||||
const properties = getPropertiesOfType(source);
|
||||
let indexInfo = getIndexInfoOfType(source, IndexKind.String);
|
||||
if (properties.length === 0 && !indexInfo) {
|
||||
|
@ -11160,7 +11160,7 @@ namespace ts {
|
|||
|
||||
function inferTargetType(sourceType: Type): Type {
|
||||
inference.candidates = undefined;
|
||||
inferTypes(inferences, sourceType, templateType);
|
||||
inferTypes(inferences, sourceType, templateType, 0, mappedTypeStack);
|
||||
return inference.candidates ? getUnionType(inference.candidates, /*subtypeReduction*/ true) : emptyObjectType;
|
||||
}
|
||||
}
|
||||
|
@ -11178,7 +11178,7 @@ namespace ts {
|
|||
return undefined;
|
||||
}
|
||||
|
||||
function inferTypes(inferences: InferenceInfo[], originalSource: Type, originalTarget: Type, priority: InferencePriority = 0) {
|
||||
function inferTypes(inferences: InferenceInfo[], originalSource: Type, originalTarget: Type, priority: InferencePriority = 0, mappedTypeStack?: [Type, Symbol][]) {
|
||||
let symbolStack: Symbol[];
|
||||
let visited: Map<boolean>;
|
||||
inferFromTypes(originalSource, originalTarget);
|
||||
|
@ -11395,7 +11395,12 @@ namespace ts {
|
|||
// such that direct inferences to T get priority over inferences to Partial<T>, for example.
|
||||
const inference = getInferenceInfoForType((<IndexType>constraintType).type);
|
||||
if (inference && !inference.isFixed) {
|
||||
const inferredType = inferTypeForHomomorphicMappedType(source, <MappedType>target);
|
||||
if (contains(mappedTypeStack, [source, target.symbol], ([s1,t1],[s2,t2]) => s1 === s2 && t1 === t2)) {
|
||||
return;
|
||||
}
|
||||
(mappedTypeStack || (mappedTypeStack = [])).push([source, target.symbol]);
|
||||
const inferredType = inferTypeForHomomorphicMappedType(source, <MappedType>target, mappedTypeStack);
|
||||
mappedTypeStack.pop();
|
||||
if (inferredType) {
|
||||
const savePriority = priority;
|
||||
priority |= InferencePriority.MappedType;
|
||||
|
|
Loading…
Reference in a new issue