Merge pull request #20370 from Microsoft/cutoff-inference-for-recursive-mapped-types

Cut off inference for recursive mapped types
This commit is contained in:
Nathan Shively-Sanders
2017-12-01 15:10:06 -08:00
committed by GitHub
5 changed files with 90 additions and 4 deletions

View File

@@ -11118,7 +11118,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: string[]): Type {
const properties = getPropertiesOfType(source);
let indexInfo = getIndexInfoOfType(source, IndexKind.String);
if (properties.length === 0 && !indexInfo) {
@@ -11151,7 +11151,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;
}
}
@@ -11169,7 +11169,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?: string[]) {
let symbolStack: Symbol[];
let visited: Map<boolean>;
inferFromTypes(originalSource, originalTarget);
@@ -11386,7 +11386,13 @@ 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);
const key = (source.symbol ? getSymbolId(source.symbol) + "," : "") + getSymbolId(target.symbol);
if (contains(mappedTypeStack, key)) {
return;
}
(mappedTypeStack || (mappedTypeStack = [])).push(key);
const inferredType = inferTypeForHomomorphicMappedType(source, <MappedType>target, mappedTypeStack);
mappedTypeStack.pop();
if (inferredType) {
const savePriority = priority;
priority |= InferencePriority.MappedType;