Fix comparability between type parameters related by a union constraint (#50978)

This commit is contained in:
Andrew Branch 2022-09-28 10:06:13 -07:00 committed by GitHub
parent b09e93d3f6
commit fbfe9340a9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 109 additions and 1 deletions

View File

@ -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;
}

View File

@ -0,0 +1,27 @@
//// [comparabilityTypeParametersRelatedByUnion.ts]
class C<T> {
constructor(readonly x: T) {}
good<U extends T>(y: U) {
if (y === this.x) {}
}
bad<U extends T | string>(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;
}());

View File

@ -0,0 +1,38 @@
=== tests/cases/compiler/comparabilityTypeParametersRelatedByUnion.ts ===
class C<T> {
>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<U extends T>(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<U extends T | string>(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))
}
}

View File

@ -0,0 +1,32 @@
=== tests/cases/compiler/comparabilityTypeParametersRelatedByUnion.ts ===
class C<T> {
>C : C<T>
constructor(readonly x: T) {}
>x : T
good<U extends T>(y: U) {
>good : <U extends T>(y: U) => void
>y : U
if (y === this.x) {}
>y === this.x : boolean
>y : U
>this.x : T
>this : this
>x : T
}
bad<U extends T | string>(y: U) {
>bad : <U extends string | T>(y: U) => void
>y : U
if (y === this.x) {}
>y === this.x : boolean
>y : U
>this.x : T
>this : this
>x : T
}
}

View File

@ -0,0 +1,11 @@
class C<T> {
constructor(readonly x: T) {}
good<U extends T>(y: U) {
if (y === this.x) {}
}
bad<U extends T | string>(y: U) {
if (y === this.x) {}
}
}