@@ -13540,6 +13540,9 @@ namespace ts {
13540
13540
if (relation !== identityRelation) {
13541
13541
source = getApparentType(source);
13542
13542
}
13543
+ else if (isGenericMappedType(source)) {
13544
+ return Ternary.False;
13545
+ }
13543
13546
if (getObjectFlags(source) & ObjectFlags.Reference && getObjectFlags(target) & ObjectFlags.Reference && (<TypeReference>source).target === (<TypeReference>target).target &&
13544
13547
!(getObjectFlags(source) & ObjectFlags.MarkerType || getObjectFlags(target) & ObjectFlags.MarkerType)) {
13545
13548
// We have type references to the same generic type, and the type references are not marker
@@ -15456,7 +15459,7 @@ namespace ts {
15456
15459
15457
15460
function inferTypes(inferences: InferenceInfo[], originalSource: Type, originalTarget: Type, priority: InferencePriority = 0, contravariant = false) {
15458
15461
let symbolStack: Symbol[];
15459
- let visited: Map<boolean >;
15462
+ let visited: Map<number >;
15460
15463
let bivariant = false;
15461
15464
let propagationType: Type;
15462
15465
let inferenceCount = 0;
@@ -15656,15 +15659,17 @@ namespace ts {
15656
15659
}
15657
15660
if (source.flags & (TypeFlags.Object | TypeFlags.Intersection)) {
15658
15661
const key = source.id + "," + target.id;
15659
- if (visited && visited.get(key)) {
15660
- inferenceBlocked = true;
15662
+ const visitCount = visited && visited.get(key);
15663
+ if (visitCount !== undefined) {
15664
+ inferenceCount += visitCount;
15661
15665
return;
15662
15666
}
15663
- (visited || (visited = createMap<boolean >())).set(key, true );
15667
+ (visited || (visited = createMap<number >())).set(key, 0 );
15664
15668
// If we are already processing another target type with the same associated symbol (such as
15665
15669
// an instantiation of the same generic type), we do not explore this target as it would yield
15666
15670
// no further inferences. We exclude the static side of classes from this check since it shares
15667
15671
// its symbol with the instance side which would lead to false positives.
15672
+ const startCount = inferenceCount;
15668
15673
const isNonConstructorObject = target.flags & TypeFlags.Object &&
15669
15674
!(getObjectFlags(target) & ObjectFlags.Anonymous && target.symbol && target.symbol.flags & SymbolFlags.Class);
15670
15675
const symbol = isNonConstructorObject ? target.symbol : undefined;
@@ -15680,14 +15685,21 @@ namespace ts {
15680
15685
else {
15681
15686
inferFromObjectTypes(source, target);
15682
15687
}
15688
+ visited.set(key, inferenceCount - startCount);
15683
15689
}
15684
15690
}
15685
15691
15686
15692
function inferFromTypesOnce(source: Type, target: Type) {
15687
15693
const key = source.id + "," + target.id;
15688
- if (!visited || !visited.get(key)) {
15689
- (visited || (visited = createMap<boolean>())).set(key, true);
15694
+ const count = visited && visited.get(key);
15695
+ if (count !== undefined) {
15696
+ inferenceCount += count;
15697
+ }
15698
+ else {
15699
+ (visited || (visited = createMap<number>())).set(key, 0);
15700
+ const startCount = inferenceCount;
15690
15701
inferFromTypes(source, target);
15702
+ visited.set(key, inferenceCount - startCount);
15691
15703
}
15692
15704
}
15693
15705
}
@@ -15780,23 +15792,28 @@ namespace ts {
15780
15792
// type variable. If there is more than one naked type variable, or if inference was blocked
15781
15793
// (meaning we didn't explore the types fully), give lower priority to the inferences as
15782
15794
// they are less specific.
15783
- if (typeVariableCount > 0 ) {
15795
+ if (typeVariableCount === 1 && !inferenceBlocked ) {
15784
15796
const unmatched = flatMap(sources, (s, i) => matched[i] ? undefined : s);
15785
15797
if (unmatched.length) {
15786
15798
const s = getUnionType(unmatched);
15787
- const savePriority = priority;
15788
- if (typeVariableCount > 1 || inferenceBlocked) {
15789
- priority |= InferencePriority.NakedTypeVariable;
15790
- }
15791
15799
for (const t of target.types) {
15792
15800
if (getInferenceInfoForType(t)) {
15793
15801
inferFromTypes(s, t);
15794
15802
}
15795
15803
}
15796
- priority = savePriority;
15797
15804
}
15798
15805
}
15799
- inferenceBlocked = saveInferenceBlocked;
15806
+ inferenceBlocked = inferenceBlocked || saveInferenceBlocked;
15807
+ if (typeVariableCount > 0) {
15808
+ const savePriority = priority;
15809
+ priority |= InferencePriority.NakedTypeVariable;
15810
+ for (const t of target.types) {
15811
+ if (getInferenceInfoForType(t)) {
15812
+ inferFromTypes(source, t);
15813
+ }
15814
+ }
15815
+ priority = savePriority;
15816
+ }
15800
15817
}
15801
15818
15802
15819
function inferToMappedType(source: Type, target: MappedType, constraintType: Type): boolean {
@@ -15958,14 +15975,13 @@ namespace ts {
15958
15975
}
15959
15976
}
15960
15977
15961
- function isTypeReferenceToSameTarget(source: Type, target: Type) {
15962
- return !!(getObjectFlags(source) & ObjectFlags.Reference && getObjectFlags(target) & ObjectFlags.Reference &&
15963
- (<TypeReference>source).target === (<TypeReference>target).target);
15978
+ function isMatchableType(type: Type) {
15979
+ return !(type.flags & TypeFlags.Object) || !!(getObjectFlags(type) & ObjectFlags.Anonymous);
15964
15980
}
15965
15981
15966
15982
function typeIdenticalToSomeType(type: Type, types: Type[]): boolean {
15967
15983
for (const t of types) {
15968
- if (t === type || !isTypeReferenceToSameTarget(t, type) && isTypeIdenticalTo(t, type)) {
15984
+ if (t === type || isMatchableType(t) && isMatchableType( type) && isTypeIdenticalTo(t, type)) {
15969
15985
return true;
15970
15986
}
15971
15987
}
0 commit comments