Skip to content

Commit 5cdf239

Browse files
authored
Fix type parameter constraint check in comparable relation (#1471)
1 parent 6d19ac2 commit 5cdf239

File tree

5 files changed

+70
-9
lines changed

5 files changed

+70
-9
lines changed

internal/checker/relater.go

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3365,15 +3365,8 @@ func (r *Relater) structuredTypeRelatedToWorker(source *Type, target *Type, repo
33653365
if r.relation == r.c.comparableRelation && source.flags&TypeFlagsTypeParameter != 0 {
33663366
// This is a carve-out in comparability to essentially forbid comparing a type parameter with another type parameter
33673367
// unless one extends the other. (Remember: comparability is mostly bidirectional!)
3368-
constraint := r.c.getConstraintOfTypeParameter(source)
3369-
if constraint != nil {
3370-
for constraint != nil && someType(constraint, func(c *Type) bool { return c.flags&TypeFlagsTypeParameter != 0 }) {
3371-
result = r.isRelatedTo(constraint, target, RecursionFlagsSource, false /*reportErrors*/)
3372-
if result != TernaryFalse {
3373-
return result
3374-
}
3375-
constraint = r.c.getConstraintOfTypeParameter(constraint)
3376-
}
3368+
if constraint := r.c.getConstraintOfTypeParameter(source); constraint != nil && someType(constraint, func(c *Type) bool { return c.flags&TypeFlagsTypeParameter != 0 }) {
3369+
return r.isRelatedTo(constraint, target, RecursionFlagsSource, false /*reportErrors*/)
33773370
}
33783371
return TernaryFalse
33793372
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
typeParameterComparableRelation.ts(6,5): error TS2352: Conversion of type 'T' to type 'A' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.
2+
'A' could be instantiated with an arbitrary type which could be unrelated to 'T'.
3+
4+
5+
==== typeParameterComparableRelation.ts (1 errors) ====
6+
// https://github.com/microsoft/typescript-go/issues/1462
7+
8+
type StringOrT<T> = T | string
9+
10+
function func<A, B, T extends StringOrT<B>>(thing: T): void {
11+
thing as A; // Error
12+
~~~~~~~~~~
13+
!!! error TS2352: Conversion of type 'T' to type 'A' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.
14+
!!! error TS2352: 'A' could be instantiated with an arbitrary type which could be unrelated to 'T'.
15+
}
16+
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
//// [tests/cases/compiler/typeParameterComparableRelation.ts] ////
2+
3+
=== typeParameterComparableRelation.ts ===
4+
// https://github.com/microsoft/typescript-go/issues/1462
5+
6+
type StringOrT<T> = T | string
7+
>StringOrT : Symbol(StringOrT, Decl(typeParameterComparableRelation.ts, 0, 0))
8+
>T : Symbol(T, Decl(typeParameterComparableRelation.ts, 2, 15))
9+
>T : Symbol(T, Decl(typeParameterComparableRelation.ts, 2, 15))
10+
11+
function func<A, B, T extends StringOrT<B>>(thing: T): void {
12+
>func : Symbol(func, Decl(typeParameterComparableRelation.ts, 2, 30))
13+
>A : Symbol(A, Decl(typeParameterComparableRelation.ts, 4, 14))
14+
>B : Symbol(B, Decl(typeParameterComparableRelation.ts, 4, 16))
15+
>T : Symbol(T, Decl(typeParameterComparableRelation.ts, 4, 19))
16+
>StringOrT : Symbol(StringOrT, Decl(typeParameterComparableRelation.ts, 0, 0))
17+
>B : Symbol(B, Decl(typeParameterComparableRelation.ts, 4, 16))
18+
>thing : Symbol(thing, Decl(typeParameterComparableRelation.ts, 4, 44))
19+
>T : Symbol(T, Decl(typeParameterComparableRelation.ts, 4, 19))
20+
21+
thing as A; // Error
22+
>thing : Symbol(thing, Decl(typeParameterComparableRelation.ts, 4, 44))
23+
>A : Symbol(A, Decl(typeParameterComparableRelation.ts, 4, 14))
24+
}
25+
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
//// [tests/cases/compiler/typeParameterComparableRelation.ts] ////
2+
3+
=== typeParameterComparableRelation.ts ===
4+
// https://github.com/microsoft/typescript-go/issues/1462
5+
6+
type StringOrT<T> = T | string
7+
>StringOrT : StringOrT<T>
8+
9+
function func<A, B, T extends StringOrT<B>>(thing: T): void {
10+
>func : <A, B, T extends StringOrT<B>>(thing: T) => void
11+
>thing : T
12+
13+
thing as A; // Error
14+
>thing as A : A
15+
>thing : T
16+
}
17+
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// @strict: true
2+
// @noEmit: true
3+
4+
// https://github.com/microsoft/typescript-go/issues/1462
5+
6+
type StringOrT<T> = T | string
7+
8+
function func<A, B, T extends StringOrT<B>>(thing: T): void {
9+
thing as A; // Error
10+
}

0 commit comments

Comments
 (0)