Skip to content

Commit fbfe934

Browse files
authoredSep 28, 2022
Fix comparability between type parameters related by a union constraint (#50978)
1 parent b09e93d commit fbfe934

5 files changed

+109
-1
lines changed
 

‎src/compiler/checker.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -19734,7 +19734,7 @@ namespace ts {
1973419734
// with another type parameter unless one extends the other. (Remember: comparability is mostly bidirectional!)
1973519735
let constraint = getConstraintOfTypeParameter(source);
1973619736
if (constraint && hasNonCircularBaseConstraint(source)) {
19737-
while (constraint && constraint.flags & TypeFlags.TypeParameter) {
19737+
while (constraint && someType(constraint, c => !!(c.flags & TypeFlags.TypeParameter))) {
1973819738
if (result = isRelatedTo(constraint, target, RecursionFlags.Source, /*reportErrors*/ false)) {
1973919739
return result;
1974019740
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
//// [comparabilityTypeParametersRelatedByUnion.ts]
2+
class C<T> {
3+
constructor(readonly x: T) {}
4+
5+
good<U extends T>(y: U) {
6+
if (y === this.x) {}
7+
}
8+
9+
bad<U extends T | string>(y: U) {
10+
if (y === this.x) {}
11+
}
12+
}
13+
14+
15+
//// [comparabilityTypeParametersRelatedByUnion.js]
16+
var C = /** @class */ (function () {
17+
function C(x) {
18+
this.x = x;
19+
}
20+
C.prototype.good = function (y) {
21+
if (y === this.x) { }
22+
};
23+
C.prototype.bad = function (y) {
24+
if (y === this.x) { }
25+
};
26+
return C;
27+
}());
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
=== tests/cases/compiler/comparabilityTypeParametersRelatedByUnion.ts ===
2+
class C<T> {
3+
>C : Symbol(C, Decl(comparabilityTypeParametersRelatedByUnion.ts, 0, 0))
4+
>T : Symbol(T, Decl(comparabilityTypeParametersRelatedByUnion.ts, 0, 8))
5+
6+
constructor(readonly x: T) {}
7+
>x : Symbol(C.x, Decl(comparabilityTypeParametersRelatedByUnion.ts, 1, 14))
8+
>T : Symbol(T, Decl(comparabilityTypeParametersRelatedByUnion.ts, 0, 8))
9+
10+
good<U extends T>(y: U) {
11+
>good : Symbol(C.good, Decl(comparabilityTypeParametersRelatedByUnion.ts, 1, 31))
12+
>U : Symbol(U, Decl(comparabilityTypeParametersRelatedByUnion.ts, 3, 7))
13+
>T : Symbol(T, Decl(comparabilityTypeParametersRelatedByUnion.ts, 0, 8))
14+
>y : Symbol(y, Decl(comparabilityTypeParametersRelatedByUnion.ts, 3, 20))
15+
>U : Symbol(U, Decl(comparabilityTypeParametersRelatedByUnion.ts, 3, 7))
16+
17+
if (y === this.x) {}
18+
>y : Symbol(y, Decl(comparabilityTypeParametersRelatedByUnion.ts, 3, 20))
19+
>this.x : Symbol(C.x, Decl(comparabilityTypeParametersRelatedByUnion.ts, 1, 14))
20+
>this : Symbol(C, Decl(comparabilityTypeParametersRelatedByUnion.ts, 0, 0))
21+
>x : Symbol(C.x, Decl(comparabilityTypeParametersRelatedByUnion.ts, 1, 14))
22+
}
23+
24+
bad<U extends T | string>(y: U) {
25+
>bad : Symbol(C.bad, Decl(comparabilityTypeParametersRelatedByUnion.ts, 5, 3))
26+
>U : Symbol(U, Decl(comparabilityTypeParametersRelatedByUnion.ts, 7, 6))
27+
>T : Symbol(T, Decl(comparabilityTypeParametersRelatedByUnion.ts, 0, 8))
28+
>y : Symbol(y, Decl(comparabilityTypeParametersRelatedByUnion.ts, 7, 28))
29+
>U : Symbol(U, Decl(comparabilityTypeParametersRelatedByUnion.ts, 7, 6))
30+
31+
if (y === this.x) {}
32+
>y : Symbol(y, Decl(comparabilityTypeParametersRelatedByUnion.ts, 7, 28))
33+
>this.x : Symbol(C.x, Decl(comparabilityTypeParametersRelatedByUnion.ts, 1, 14))
34+
>this : Symbol(C, Decl(comparabilityTypeParametersRelatedByUnion.ts, 0, 0))
35+
>x : Symbol(C.x, Decl(comparabilityTypeParametersRelatedByUnion.ts, 1, 14))
36+
}
37+
}
38+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
=== tests/cases/compiler/comparabilityTypeParametersRelatedByUnion.ts ===
2+
class C<T> {
3+
>C : C<T>
4+
5+
constructor(readonly x: T) {}
6+
>x : T
7+
8+
good<U extends T>(y: U) {
9+
>good : <U extends T>(y: U) => void
10+
>y : U
11+
12+
if (y === this.x) {}
13+
>y === this.x : boolean
14+
>y : U
15+
>this.x : T
16+
>this : this
17+
>x : T
18+
}
19+
20+
bad<U extends T | string>(y: U) {
21+
>bad : <U extends string | T>(y: U) => void
22+
>y : U
23+
24+
if (y === this.x) {}
25+
>y === this.x : boolean
26+
>y : U
27+
>this.x : T
28+
>this : this
29+
>x : T
30+
}
31+
}
32+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
class C<T> {
2+
constructor(readonly x: T) {}
3+
4+
good<U extends T>(y: U) {
5+
if (y === this.x) {}
6+
}
7+
8+
bad<U extends T | string>(y: U) {
9+
if (y === this.x) {}
10+
}
11+
}

0 commit comments

Comments
 (0)
Please sign in to comment.