Skip to content

Commit 3ec1b04

Browse files
authored
Add explicit tests for unconstrained type param not being assignable to {} and Record<string, any> (#48421)
1 parent a7608e1 commit 3ec1b04

5 files changed

+212
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
tests/cases/compiler/genericUnboundedTypeParamAssignability.ts(2,5): error TS2339: Property 'toString' does not exist on type 'T'.
2+
tests/cases/compiler/genericUnboundedTypeParamAssignability.ts(15,6): error TS2345: Argument of type 'T' is not assignable to parameter of type '{}'.
3+
tests/cases/compiler/genericUnboundedTypeParamAssignability.ts(16,6): error TS2345: Argument of type 'T' is not assignable to parameter of type 'Record<string, any>'.
4+
tests/cases/compiler/genericUnboundedTypeParamAssignability.ts(17,5): error TS2339: Property 'toString' does not exist on type 'T'.
5+
6+
7+
==== tests/cases/compiler/genericUnboundedTypeParamAssignability.ts (4 errors) ====
8+
function f1<T>(o: T) {
9+
o.toString(); // error
10+
~~~~~~~~
11+
!!! error TS2339: Property 'toString' does not exist on type 'T'.
12+
}
13+
14+
function f2<T extends {}>(o: T) {
15+
o.toString(); // no error
16+
}
17+
18+
function f3<T extends Record<string, any>>(o: T) {
19+
o.toString(); // no error
20+
}
21+
22+
function user<T>(t: T) {
23+
f1(t);
24+
f2(t); // error in strict, unbounded T doesn't satisfy the constraint
25+
~
26+
!!! error TS2345: Argument of type 'T' is not assignable to parameter of type '{}'.
27+
!!! related TS2208 tests/cases/compiler/genericUnboundedTypeParamAssignability.ts:13:15: This type parameter probably needs an `extends object` constraint.
28+
f3(t); // error in strict, unbounded T doesn't satisfy the constraint
29+
~
30+
!!! error TS2345: Argument of type 'T' is not assignable to parameter of type 'Record<string, any>'.
31+
!!! related TS2208 tests/cases/compiler/genericUnboundedTypeParamAssignability.ts:13:15: This type parameter probably needs an `extends object` constraint.
32+
t.toString(); // error, for the same reason as f1()
33+
~~~~~~~~
34+
!!! error TS2339: Property 'toString' does not exist on type 'T'.
35+
}
36+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
//// [genericUnboundedTypeParamAssignability.ts]
2+
function f1<T>(o: T) {
3+
o.toString(); // error
4+
}
5+
6+
function f2<T extends {}>(o: T) {
7+
o.toString(); // no error
8+
}
9+
10+
function f3<T extends Record<string, any>>(o: T) {
11+
o.toString(); // no error
12+
}
13+
14+
function user<T>(t: T) {
15+
f1(t);
16+
f2(t); // error in strict, unbounded T doesn't satisfy the constraint
17+
f3(t); // error in strict, unbounded T doesn't satisfy the constraint
18+
t.toString(); // error, for the same reason as f1()
19+
}
20+
21+
22+
//// [genericUnboundedTypeParamAssignability.js]
23+
"use strict";
24+
function f1(o) {
25+
o.toString(); // error
26+
}
27+
function f2(o) {
28+
o.toString(); // no error
29+
}
30+
function f3(o) {
31+
o.toString(); // no error
32+
}
33+
function user(t) {
34+
f1(t);
35+
f2(t); // error in strict, unbounded T doesn't satisfy the constraint
36+
f3(t); // error in strict, unbounded T doesn't satisfy the constraint
37+
t.toString(); // error, for the same reason as f1()
38+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
=== tests/cases/compiler/genericUnboundedTypeParamAssignability.ts ===
2+
function f1<T>(o: T) {
3+
>f1 : Symbol(f1, Decl(genericUnboundedTypeParamAssignability.ts, 0, 0))
4+
>T : Symbol(T, Decl(genericUnboundedTypeParamAssignability.ts, 0, 12))
5+
>o : Symbol(o, Decl(genericUnboundedTypeParamAssignability.ts, 0, 15))
6+
>T : Symbol(T, Decl(genericUnboundedTypeParamAssignability.ts, 0, 12))
7+
8+
o.toString(); // error
9+
>o : Symbol(o, Decl(genericUnboundedTypeParamAssignability.ts, 0, 15))
10+
}
11+
12+
function f2<T extends {}>(o: T) {
13+
>f2 : Symbol(f2, Decl(genericUnboundedTypeParamAssignability.ts, 2, 1))
14+
>T : Symbol(T, Decl(genericUnboundedTypeParamAssignability.ts, 4, 12))
15+
>o : Symbol(o, Decl(genericUnboundedTypeParamAssignability.ts, 4, 26))
16+
>T : Symbol(T, Decl(genericUnboundedTypeParamAssignability.ts, 4, 12))
17+
18+
o.toString(); // no error
19+
>o.toString : Symbol(Object.toString, Decl(lib.es5.d.ts, --, --))
20+
>o : Symbol(o, Decl(genericUnboundedTypeParamAssignability.ts, 4, 26))
21+
>toString : Symbol(Object.toString, Decl(lib.es5.d.ts, --, --))
22+
}
23+
24+
function f3<T extends Record<string, any>>(o: T) {
25+
>f3 : Symbol(f3, Decl(genericUnboundedTypeParamAssignability.ts, 6, 1))
26+
>T : Symbol(T, Decl(genericUnboundedTypeParamAssignability.ts, 8, 12))
27+
>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --))
28+
>o : Symbol(o, Decl(genericUnboundedTypeParamAssignability.ts, 8, 43))
29+
>T : Symbol(T, Decl(genericUnboundedTypeParamAssignability.ts, 8, 12))
30+
31+
o.toString(); // no error
32+
>o.toString : Symbol(Object.toString, Decl(lib.es5.d.ts, --, --))
33+
>o : Symbol(o, Decl(genericUnboundedTypeParamAssignability.ts, 8, 43))
34+
>toString : Symbol(Object.toString, Decl(lib.es5.d.ts, --, --))
35+
}
36+
37+
function user<T>(t: T) {
38+
>user : Symbol(user, Decl(genericUnboundedTypeParamAssignability.ts, 10, 1))
39+
>T : Symbol(T, Decl(genericUnboundedTypeParamAssignability.ts, 12, 14))
40+
>t : Symbol(t, Decl(genericUnboundedTypeParamAssignability.ts, 12, 17))
41+
>T : Symbol(T, Decl(genericUnboundedTypeParamAssignability.ts, 12, 14))
42+
43+
f1(t);
44+
>f1 : Symbol(f1, Decl(genericUnboundedTypeParamAssignability.ts, 0, 0))
45+
>t : Symbol(t, Decl(genericUnboundedTypeParamAssignability.ts, 12, 17))
46+
47+
f2(t); // error in strict, unbounded T doesn't satisfy the constraint
48+
>f2 : Symbol(f2, Decl(genericUnboundedTypeParamAssignability.ts, 2, 1))
49+
>t : Symbol(t, Decl(genericUnboundedTypeParamAssignability.ts, 12, 17))
50+
51+
f3(t); // error in strict, unbounded T doesn't satisfy the constraint
52+
>f3 : Symbol(f3, Decl(genericUnboundedTypeParamAssignability.ts, 6, 1))
53+
>t : Symbol(t, Decl(genericUnboundedTypeParamAssignability.ts, 12, 17))
54+
55+
t.toString(); // error, for the same reason as f1()
56+
>t : Symbol(t, Decl(genericUnboundedTypeParamAssignability.ts, 12, 17))
57+
}
58+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
=== tests/cases/compiler/genericUnboundedTypeParamAssignability.ts ===
2+
function f1<T>(o: T) {
3+
>f1 : <T>(o: T) => void
4+
>o : T
5+
6+
o.toString(); // error
7+
>o.toString() : any
8+
>o.toString : any
9+
>o : T
10+
>toString : any
11+
}
12+
13+
function f2<T extends {}>(o: T) {
14+
>f2 : <T extends {}>(o: T) => void
15+
>o : T
16+
17+
o.toString(); // no error
18+
>o.toString() : string
19+
>o.toString : () => string
20+
>o : T
21+
>toString : () => string
22+
}
23+
24+
function f3<T extends Record<string, any>>(o: T) {
25+
>f3 : <T extends Record<string, any>>(o: T) => void
26+
>o : T
27+
28+
o.toString(); // no error
29+
>o.toString() : string
30+
>o.toString : () => string
31+
>o : T
32+
>toString : () => string
33+
}
34+
35+
function user<T>(t: T) {
36+
>user : <T>(t: T) => void
37+
>t : T
38+
39+
f1(t);
40+
>f1(t) : void
41+
>f1 : <T>(o: T) => void
42+
>t : T
43+
44+
f2(t); // error in strict, unbounded T doesn't satisfy the constraint
45+
>f2(t) : void
46+
>f2 : <T extends {}>(o: T) => void
47+
>t : T
48+
49+
f3(t); // error in strict, unbounded T doesn't satisfy the constraint
50+
>f3(t) : void
51+
>f3 : <T extends Record<string, any>>(o: T) => void
52+
>t : T
53+
54+
t.toString(); // error, for the same reason as f1()
55+
>t.toString() : any
56+
>t.toString : any
57+
>t : T
58+
>toString : any
59+
}
60+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// @strict: true
2+
3+
function f1<T>(o: T) {
4+
o.toString(); // error
5+
}
6+
7+
function f2<T extends {}>(o: T) {
8+
o.toString(); // no error
9+
}
10+
11+
function f3<T extends Record<string, any>>(o: T) {
12+
o.toString(); // no error
13+
}
14+
15+
function user<T>(t: T) {
16+
f1(t);
17+
f2(t); // error in strict, unbounded T doesn't satisfy the constraint
18+
f3(t); // error in strict, unbounded T doesn't satisfy the constraint
19+
t.toString(); // error, for the same reason as f1()
20+
}

0 commit comments

Comments
 (0)