diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 20d075cdfc07f..5af10d2b76808 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -19734,7 +19734,7 @@ namespace ts { // with another type parameter unless one extends the other. (Remember: comparability is mostly bidirectional!) let constraint = getConstraintOfTypeParameter(source); if (constraint && hasNonCircularBaseConstraint(source)) { - while (constraint && constraint.flags & TypeFlags.TypeParameter) { + while (constraint && someType(constraint, c => !!(c.flags & TypeFlags.TypeParameter))) { if (result = isRelatedTo(constraint, target, RecursionFlags.Source, /*reportErrors*/ false)) { return result; } diff --git a/tests/baselines/reference/comparabilityTypeParametersRelatedByUnion.js b/tests/baselines/reference/comparabilityTypeParametersRelatedByUnion.js new file mode 100644 index 0000000000000..a0e56a3dd66de --- /dev/null +++ b/tests/baselines/reference/comparabilityTypeParametersRelatedByUnion.js @@ -0,0 +1,27 @@ +//// [comparabilityTypeParametersRelatedByUnion.ts] +class C { + constructor(readonly x: T) {} + + good(y: U) { + if (y === this.x) {} + } + + bad(y: U) { + if (y === this.x) {} + } +} + + +//// [comparabilityTypeParametersRelatedByUnion.js] +var C = /** @class */ (function () { + function C(x) { + this.x = x; + } + C.prototype.good = function (y) { + if (y === this.x) { } + }; + C.prototype.bad = function (y) { + if (y === this.x) { } + }; + return C; +}()); diff --git a/tests/baselines/reference/comparabilityTypeParametersRelatedByUnion.symbols b/tests/baselines/reference/comparabilityTypeParametersRelatedByUnion.symbols new file mode 100644 index 0000000000000..482900c650c8b --- /dev/null +++ b/tests/baselines/reference/comparabilityTypeParametersRelatedByUnion.symbols @@ -0,0 +1,38 @@ +=== tests/cases/compiler/comparabilityTypeParametersRelatedByUnion.ts === +class C { +>C : Symbol(C, Decl(comparabilityTypeParametersRelatedByUnion.ts, 0, 0)) +>T : Symbol(T, Decl(comparabilityTypeParametersRelatedByUnion.ts, 0, 8)) + + constructor(readonly x: T) {} +>x : Symbol(C.x, Decl(comparabilityTypeParametersRelatedByUnion.ts, 1, 14)) +>T : Symbol(T, Decl(comparabilityTypeParametersRelatedByUnion.ts, 0, 8)) + + good(y: U) { +>good : Symbol(C.good, Decl(comparabilityTypeParametersRelatedByUnion.ts, 1, 31)) +>U : Symbol(U, Decl(comparabilityTypeParametersRelatedByUnion.ts, 3, 7)) +>T : Symbol(T, Decl(comparabilityTypeParametersRelatedByUnion.ts, 0, 8)) +>y : Symbol(y, Decl(comparabilityTypeParametersRelatedByUnion.ts, 3, 20)) +>U : Symbol(U, Decl(comparabilityTypeParametersRelatedByUnion.ts, 3, 7)) + + if (y === this.x) {} +>y : Symbol(y, Decl(comparabilityTypeParametersRelatedByUnion.ts, 3, 20)) +>this.x : Symbol(C.x, Decl(comparabilityTypeParametersRelatedByUnion.ts, 1, 14)) +>this : Symbol(C, Decl(comparabilityTypeParametersRelatedByUnion.ts, 0, 0)) +>x : Symbol(C.x, Decl(comparabilityTypeParametersRelatedByUnion.ts, 1, 14)) + } + + bad(y: U) { +>bad : Symbol(C.bad, Decl(comparabilityTypeParametersRelatedByUnion.ts, 5, 3)) +>U : Symbol(U, Decl(comparabilityTypeParametersRelatedByUnion.ts, 7, 6)) +>T : Symbol(T, Decl(comparabilityTypeParametersRelatedByUnion.ts, 0, 8)) +>y : Symbol(y, Decl(comparabilityTypeParametersRelatedByUnion.ts, 7, 28)) +>U : Symbol(U, Decl(comparabilityTypeParametersRelatedByUnion.ts, 7, 6)) + + if (y === this.x) {} +>y : Symbol(y, Decl(comparabilityTypeParametersRelatedByUnion.ts, 7, 28)) +>this.x : Symbol(C.x, Decl(comparabilityTypeParametersRelatedByUnion.ts, 1, 14)) +>this : Symbol(C, Decl(comparabilityTypeParametersRelatedByUnion.ts, 0, 0)) +>x : Symbol(C.x, Decl(comparabilityTypeParametersRelatedByUnion.ts, 1, 14)) + } +} + diff --git a/tests/baselines/reference/comparabilityTypeParametersRelatedByUnion.types b/tests/baselines/reference/comparabilityTypeParametersRelatedByUnion.types new file mode 100644 index 0000000000000..f2d380552d801 --- /dev/null +++ b/tests/baselines/reference/comparabilityTypeParametersRelatedByUnion.types @@ -0,0 +1,32 @@ +=== tests/cases/compiler/comparabilityTypeParametersRelatedByUnion.ts === +class C { +>C : C + + constructor(readonly x: T) {} +>x : T + + good(y: U) { +>good : (y: U) => void +>y : U + + if (y === this.x) {} +>y === this.x : boolean +>y : U +>this.x : T +>this : this +>x : T + } + + bad(y: U) { +>bad : (y: U) => void +>y : U + + if (y === this.x) {} +>y === this.x : boolean +>y : U +>this.x : T +>this : this +>x : T + } +} + diff --git a/tests/cases/compiler/comparabilityTypeParametersRelatedByUnion.ts b/tests/cases/compiler/comparabilityTypeParametersRelatedByUnion.ts new file mode 100644 index 0000000000000..1e9f0eb6e227d --- /dev/null +++ b/tests/cases/compiler/comparabilityTypeParametersRelatedByUnion.ts @@ -0,0 +1,11 @@ +class C { + constructor(readonly x: T) {} + + good(y: U) { + if (y === this.x) {} + } + + bad(y: U) { + if (y === this.x) {} + } +}