@@ -8949,36 +8949,36 @@ namespace ts {
8949
8949
target = (<LiteralType>target).regularType;
8950
8950
}
8951
8951
// both types are the same - covers 'they are the same primitive type or both are Any' or the same type parameter cases
8952
- if (source === target) return Ternary.True;
8952
+ if (source === target || relation !== identityRelation && isSimpleTypeRelatedTo(source, target, relation, reportErrors ? reportError : undefined)) {
8953
+ return Ternary.True;
8954
+ }
8953
8955
8954
- const comparisonId = getRelationKey(source, target, relation);
8955
- if ( relation.has(comparisonId)) {
8956
- const result = relation.get(comparisonId);
8956
+ const id = getRelationKey(source, target, relation);
8957
+ const related = relation.get(id);
8958
+ if (related !== undefined) {
8957
8959
// If we need to report errors, and the result is RelationComparisonResult.Failed, then we need
8958
8960
// to redo our work to generate an error message. Otherwise, we can just return the cached result.
8959
- if (!reportErrors || result !== RelationComparisonResult.Failed) {
8960
- if (reportErrors && result !== RelationComparisonResult.Succeeded) {
8961
+ if (!reportErrors || related !== RelationComparisonResult.Failed) {
8962
+ if (reportErrors && related !== RelationComparisonResult.Succeeded) {
8961
8963
reportElaboratedRelationError(headMessage, source, target);
8962
8964
}
8963
- return result === RelationComparisonResult.Succeeded ? Ternary.True : Ternary.False;
8965
+ return related === RelationComparisonResult.Succeeded ? Ternary.True : Ternary.False;
8964
8966
}
8965
- if (reportErrors && result === RelationComparisonResult.Failed) {
8966
- relation.set(comparisonId , RelationComparisonResult.FailedAndReported);
8967
+ if (reportErrors && related === RelationComparisonResult.Failed) {
8968
+ relation.set(id , RelationComparisonResult.FailedAndReported);
8967
8969
}
8968
8970
}
8969
8971
8970
8972
if (relation === identityRelation) {
8971
- return cacheResult(isIdenticalTo(source, target), comparisonId , /*reportErrors*/ false);
8973
+ return cacheResult(isIdenticalTo(source, target, id ), id , /*reportErrors*/ false);
8972
8974
}
8973
8975
8974
- if (isSimpleTypeRelatedTo(source, target, relation, reportErrors ? reportError : undefined)) return Ternary.True;
8975
-
8976
8976
if (getObjectFlags(source) & ObjectFlags.ObjectLiteral && source.flags & TypeFlags.FreshLiteral) {
8977
8977
if (hasExcessProperties(<FreshObjectLiteralType>source, target, reportErrors)) {
8978
8978
if (reportErrors) {
8979
8979
reportRelationError(headMessage, source, target);
8980
8980
}
8981
- return cacheResult(Ternary.False, comparisonId , reportErrors);
8981
+ return cacheResult(Ternary.False, id , reportErrors);
8982
8982
}
8983
8983
// Above we check for excess properties with respect to the entire target type. When union
8984
8984
// and intersection types are further deconstructed on the target side, we don't want to
@@ -9052,7 +9052,7 @@ namespace ts {
9052
9052
result = someTypeRelatedToType(<IntersectionType>source, target, /*reportErrors*/ false);
9053
9053
}
9054
9054
if (!result && (source.flags & TypeFlags.StructuredOrTypeVariable || target.flags & TypeFlags.StructuredOrTypeVariable)) {
9055
- if (result = recursiveTypeRelatedTo(source, target, reportErrors)) {
9055
+ if (result = recursiveTypeRelatedTo(source, target, id, reportErrors)) {
9056
9056
errorInfo = saveErrorInfo;
9057
9057
}
9058
9058
}
@@ -9064,7 +9064,7 @@ namespace ts {
9064
9064
reportElaboratedRelationError(headMessage, source, target);
9065
9065
}
9066
9066
9067
- return cacheResult(result, comparisonId , reportErrors);
9067
+ return cacheResult(result, id , reportErrors);
9068
9068
}
9069
9069
9070
9070
function cacheResult(result: Ternary, comparisonId: string, reportErrors?: boolean) {
@@ -9074,10 +9074,10 @@ namespace ts {
9074
9074
return result;
9075
9075
}
9076
9076
9077
- function isIdenticalTo(source: Type, target: Type): Ternary {
9077
+ function isIdenticalTo(source: Type, target: Type, id: string ): Ternary {
9078
9078
let result: Ternary;
9079
9079
if (source.flags & TypeFlags.Object && target.flags & TypeFlags.Object) {
9080
- return recursiveTypeRelatedTo(source, target, /*reportErrors*/ false);
9080
+ return recursiveTypeRelatedTo(source, target, id, /*reportErrors*/ false);
9081
9081
}
9082
9082
if (source.flags & TypeFlags.Union && target.flags & TypeFlags.Union ||
9083
9083
source.flags & TypeFlags.Intersection && target.flags & TypeFlags.Intersection) {
@@ -9238,11 +9238,10 @@ namespace ts {
9238
9238
// Third, check if both types are part of deeply nested chains of generic type instantiations and if so assume the types are
9239
9239
// equal and infinitely expanding. Fourth, if we have reached a depth of 100 nested comparisons, assume we have runaway recursion
9240
9240
// and issue an error. Otherwise, actually compare the structure of the two types.
9241
- function recursiveTypeRelatedTo(source: Type, target: Type, reportErrors: boolean): Ternary {
9241
+ function recursiveTypeRelatedTo(source: Type, target: Type, id: string, reportErrors: boolean): Ternary {
9242
9242
if (overflow) {
9243
9243
return Ternary.False;
9244
9244
}
9245
- const id = getRelationKey(source, target, relation);
9246
9245
if (!maybeKeys) {
9247
9246
maybeKeys = [];
9248
9247
sourceStack = [];
0 commit comments