Skip to content

Commit 6e736c1

Browse files
Josh GoldbergRyanCavanaugh
Josh Goldberg
authored andcommitted
Added custom error message when trying to assign constraint type to generic type parameter (#30394)
* Added custom error message when trying to assign constraint type to generic type parameter Fixes #29049. This also adds the new message in chained error messages. `typeParameterDiamond4.errors.txt` shows it appearing twice in the "diamond" scenario. I can't tell if this severely increased amount of nested messages is good or bad...? * Updated diagnostic message per suggestion * Align formatting with local custom
1 parent 7016d45 commit 6e736c1

File tree

102 files changed

+919
-156
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

102 files changed

+919
-156
lines changed

src/compiler/checker.ts

+9
Original file line numberDiff line numberDiff line change
@@ -12328,6 +12328,15 @@ namespace ts {
1232812328
function reportRelationError(message: DiagnosticMessage | undefined, source: Type, target: Type) {
1232912329
const [sourceType, targetType] = getTypeNamesForErrorDisplay(source, target);
1233012330

12331+
if (target.flags & TypeFlags.TypeParameter && target.immediateBaseConstraint !== undefined && isTypeAssignableTo(source, target.immediateBaseConstraint)) {
12332+
reportError(
12333+
Diagnostics._0_is_assignable_to_the_constraint_of_type_1_but_1_could_be_instantiated_with_a_different_subtype_of_constraint_2,
12334+
sourceType,
12335+
targetType,
12336+
typeToString(target.immediateBaseConstraint),
12337+
);
12338+
}
12339+
1233112340
if (!message) {
1233212341
if (relation === comparableRelation) {
1233312342
message = Diagnostics.Type_0_is_not_comparable_to_type_1;

src/compiler/diagnosticMessages.json

+4
Original file line numberDiff line numberDiff line change
@@ -3096,6 +3096,10 @@
30963096
"category": "Error",
30973097
"code": 5074
30983098
},
3099+
"'{0}' is assignable to the constraint of type '{1}', but '{1}' could be instantiated with a different subtype of constraint '{2}'.": {
3100+
"category": "Error",
3101+
"code": 5075
3102+
},
30993103

31003104
"Generates a sourcemap for each corresponding '.d.ts' file.": {
31013105
"category": "Message",

tests/baselines/reference/assignmentCompatWithCallSignatures3.errors.txt

+14
Original file line numberDiff line numberDiff line change
@@ -14,24 +14,30 @@ tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignme
1414
Types of parameters 'x' and 'x' are incompatible.
1515
Types of parameters 'arg' and 'arg' are incompatible.
1616
Type 'string' is not assignable to type 'T'.
17+
'string' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint '{}'.
1718
tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithCallSignatures3.ts(62,1): error TS2322: Type '(x: (arg: Base) => Derived) => Base' is not assignable to type '<T extends Base, U extends Derived>(x: (arg: T) => U) => T'.
1819
Types of parameters 'x' and 'x' are incompatible.
1920
Types of parameters 'arg' and 'arg' are incompatible.
2021
Type 'Base' is not assignable to type 'T'.
22+
'Base' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint 'Base'.
2123
tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithCallSignatures3.ts(65,1): error TS2322: Type '(x: (arg: Base) => Derived) => (r: Base) => Derived' is not assignable to type '<T extends Base, U extends Derived>(x: (arg: T) => U) => (r: T) => U'.
2224
Types of parameters 'x' and 'x' are incompatible.
2325
Types of parameters 'arg' and 'arg' are incompatible.
2426
Type 'Base' is not assignable to type 'T'.
27+
'Base' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint 'Base'.
2528
tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithCallSignatures3.ts(68,1): error TS2322: Type '(x: (arg: Base) => Derived, y: (arg2: Base) => Derived) => (r: Base) => Derived' is not assignable to type '<T extends Base, U extends Derived>(x: (arg: T) => U, y: (arg2: T) => U) => (r: T) => U'.
2629
Types of parameters 'x' and 'x' are incompatible.
2730
Types of parameters 'arg' and 'arg' are incompatible.
2831
Type 'Base' is not assignable to type 'T'.
32+
'Base' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint 'Base'.
2933
tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithCallSignatures3.ts(71,1): error TS2322: Type '(x: (arg: Base) => Derived, y: (arg2: Base) => Derived) => (r: Base) => Derived' is not assignable to type '<T extends Base, U extends Derived>(x: (arg: T) => U, y: (arg2: { foo: string; bing: number; }) => U) => (r: T) => U'.
3034
Types of parameters 'x' and 'x' are incompatible.
3135
Types of parameters 'arg' and 'arg' are incompatible.
3236
Type 'Base' is not assignable to type 'T'.
37+
'Base' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint 'Base'.
3338
tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithCallSignatures3.ts(74,1): error TS2322: Type '(...x: Derived[]) => Derived' is not assignable to type '<T extends Derived>(...x: T[]) => T'.
3439
Type 'Derived' is not assignable to type 'T'.
40+
'Derived' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint 'Derived'.
3541
tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithCallSignatures3.ts(77,1): error TS2322: Type '(x: { foo: string; }, y: { foo: string; bar: string; }) => Base' is not assignable to type '<T extends Base>(x: T, y: T) => T'.
3642
Types of parameters 'y' and 'y' are incompatible.
3743
Type 'T' is not assignable to type '{ foo: string; bar: string; }'.
@@ -43,6 +49,7 @@ tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignme
4349
Type 'Base' is missing the following properties from type 'Derived2': baz, bar
4450
tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithCallSignatures3.ts(83,1): error TS2322: Type '(x: Base[], y: Derived[]) => Derived[]' is not assignable to type '<T extends Derived[]>(x: Base[], y: T) => T'.
4551
Type 'Derived[]' is not assignable to type 'T'.
52+
'Derived[]' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint 'Derived[]'.
4653
tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithCallSignatures3.ts(85,1): error TS2322: Type '<T>(x: { a: T; b: T; }) => T' is not assignable to type '(x: { a: string; b: number; }) => Object'.
4754
Types of parameters 'x' and 'x' are incompatible.
4855
Type '{ a: string; b: number; }' is not assignable to type '{ a: string; b: string; }'.
@@ -136,6 +143,7 @@ tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignme
136143
!!! error TS2322: Types of parameters 'x' and 'x' are incompatible.
137144
!!! error TS2322: Types of parameters 'arg' and 'arg' are incompatible.
138145
!!! error TS2322: Type 'string' is not assignable to type 'T'.
146+
!!! error TS2322: 'string' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint '{}'.
139147
var b6: <T extends Base, U extends Derived>(x: (arg: T) => U) => T;
140148
a6 = b6; // ok
141149
b6 = a6; // ok
@@ -144,6 +152,7 @@ tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignme
144152
!!! error TS2322: Types of parameters 'x' and 'x' are incompatible.
145153
!!! error TS2322: Types of parameters 'arg' and 'arg' are incompatible.
146154
!!! error TS2322: Type 'Base' is not assignable to type 'T'.
155+
!!! error TS2322: 'Base' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint 'Base'.
147156
var b7: <T extends Base, U extends Derived>(x: (arg: T) => U) => (r: T) => U;
148157
a7 = b7; // ok
149158
b7 = a7; // ok
@@ -152,6 +161,7 @@ tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignme
152161
!!! error TS2322: Types of parameters 'x' and 'x' are incompatible.
153162
!!! error TS2322: Types of parameters 'arg' and 'arg' are incompatible.
154163
!!! error TS2322: Type 'Base' is not assignable to type 'T'.
164+
!!! error TS2322: 'Base' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint 'Base'.
155165
var b8: <T extends Base, U extends Derived>(x: (arg: T) => U, y: (arg2: T) => U) => (r: T) => U;
156166
a8 = b8; // ok
157167
b8 = a8; // ok
@@ -160,6 +170,7 @@ tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignme
160170
!!! error TS2322: Types of parameters 'x' and 'x' are incompatible.
161171
!!! error TS2322: Types of parameters 'arg' and 'arg' are incompatible.
162172
!!! error TS2322: Type 'Base' is not assignable to type 'T'.
173+
!!! error TS2322: 'Base' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint 'Base'.
163174
var b9: <T extends Base, U extends Derived>(x: (arg: T) => U, y: (arg2: { foo: string; bing: number }) => U) => (r: T) => U;
164175
a9 = b9; // ok
165176
b9 = a9; // ok
@@ -168,12 +179,14 @@ tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignme
168179
!!! error TS2322: Types of parameters 'x' and 'x' are incompatible.
169180
!!! error TS2322: Types of parameters 'arg' and 'arg' are incompatible.
170181
!!! error TS2322: Type 'Base' is not assignable to type 'T'.
182+
!!! error TS2322: 'Base' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint 'Base'.
171183
var b10: <T extends Derived>(...x: T[]) => T;
172184
a10 = b10; // ok
173185
b10 = a10; // ok
174186
~~~
175187
!!! error TS2322: Type '(...x: Derived[]) => Derived' is not assignable to type '<T extends Derived>(...x: T[]) => T'.
176188
!!! error TS2322: Type 'Derived' is not assignable to type 'T'.
189+
!!! error TS2322: 'Derived' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint 'Derived'.
177190
var b11: <T extends Base>(x: T, y: T) => T;
178191
a11 = b11; // ok
179192
b11 = a11; // ok
@@ -198,6 +211,7 @@ tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignme
198211
~~~
199212
!!! error TS2322: Type '(x: Base[], y: Derived[]) => Derived[]' is not assignable to type '<T extends Derived[]>(x: Base[], y: T) => T'.
200213
!!! error TS2322: Type 'Derived[]' is not assignable to type 'T'.
214+
!!! error TS2322: 'Derived[]' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint 'Derived[]'.
201215
var b14: <T>(x: { a: T; b: T }) => T;
202216
a14 = b14; // ok
203217
~~~

tests/baselines/reference/assignmentCompatWithCallSignatures4.errors.txt

+8
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignme
55
Types of parameters 'x' and 'x' are incompatible.
66
Types of parameters 'arg' and 'arg' are incompatible.
77
Type 'Base' is not assignable to type 'T'.
8+
'Base' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint 'Base'.
89
tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithCallSignatures4.ts(52,9): error TS2322: Type '<T extends Base, U extends Derived>(x: (arg: T) => U, y: (arg2: { foo: number; }) => U) => (r: T) => U' is not assignable to type '(x: (arg: Base) => Derived, y: (arg2: Base) => Derived) => (r: Base) => Derived'.
910
Types of parameters 'y' and 'y' are incompatible.
1011
Types of parameters 'arg2' and 'arg2' are incompatible.
@@ -15,6 +16,7 @@ tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignme
1516
Types of parameters 'x' and 'x' are incompatible.
1617
Types of parameters 'arg' and 'arg' are incompatible.
1718
Type 'Base' is not assignable to type 'T'.
19+
'Base' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint 'Base'.
1820
tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithCallSignatures4.ts(58,9): error TS2322: Type '(...x: Base[]) => Base' is not assignable to type '<T extends Derived>(...x: T[]) => T'.
1921
Type 'Base' is not assignable to type 'T'.
2022
tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithCallSignatures4.ts(62,9): error TS2322: Type '(x: { foo: string; }, y: { foo: string; bar: string; }) => Base' is not assignable to type '<T extends Derived>(x: T, y: T) => T'.
@@ -45,6 +47,7 @@ tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignme
4547
tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithCallSignatures4.ts(89,9): error TS2322: Type '<T>(x: T) => string[]' is not assignable to type '<T>(x: T) => T[]'.
4648
Type 'string[]' is not assignable to type 'T[]'.
4749
Type 'string' is not assignable to type 'T'.
50+
'string' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint '{}'.
4851
tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithCallSignatures4.ts(90,9): error TS2322: Type '<T>(x: T) => T[]' is not assignable to type '<T>(x: T) => string[]'.
4952
Type 'T[]' is not assignable to type 'string[]'.
5053
Type 'T' is not assignable to type 'string'.
@@ -54,6 +57,7 @@ tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignme
5457
tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithCallSignatures4.ts(96,9): error TS2322: Type '<T>(x: T) => string[]' is not assignable to type '<T>(x: T) => T[]'.
5558
Type 'string[]' is not assignable to type 'T[]'.
5659
Type 'string' is not assignable to type 'T'.
60+
'string' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint '{}'.
5761

5862

5963
==== tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithCallSignatures4.ts (15 errors) ====
@@ -115,6 +119,7 @@ tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignme
115119
!!! error TS2322: Types of parameters 'x' and 'x' are incompatible.
116120
!!! error TS2322: Types of parameters 'arg' and 'arg' are incompatible.
117121
!!! error TS2322: Type 'Base' is not assignable to type 'T'.
122+
!!! error TS2322: 'Base' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint 'Base'.
118123

119124
var b8: <T extends Base, U extends Derived>(x: (arg: T) => U, y: (arg2: { foo: number; }) => U) => (r: T) => U;
120125
a8 = b8; // error, { foo: number } and Base are incompatible
@@ -131,6 +136,7 @@ tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignme
131136
!!! error TS2322: Types of parameters 'x' and 'x' are incompatible.
132137
!!! error TS2322: Types of parameters 'arg' and 'arg' are incompatible.
133138
!!! error TS2322: Type 'Base' is not assignable to type 'T'.
139+
!!! error TS2322: 'Base' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint 'Base'.
134140

135141

136142
var b10: <T extends Derived>(...x: T[]) => T;
@@ -205,6 +211,7 @@ tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignme
205211
!!! error TS2322: Type '<T>(x: T) => string[]' is not assignable to type '<T>(x: T) => T[]'.
206212
!!! error TS2322: Type 'string[]' is not assignable to type 'T[]'.
207213
!!! error TS2322: Type 'string' is not assignable to type 'T'.
214+
!!! error TS2322: 'string' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint '{}'.
208215
b2 = a2;
209216
~~
210217
!!! error TS2322: Type '<T>(x: T) => T[]' is not assignable to type '<T>(x: T) => string[]'.
@@ -224,5 +231,6 @@ tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignme
224231
!!! error TS2322: Type '<T>(x: T) => string[]' is not assignable to type '<T>(x: T) => T[]'.
225232
!!! error TS2322: Type 'string[]' is not assignable to type 'T[]'.
226233
!!! error TS2322: Type 'string' is not assignable to type 'T'.
234+
!!! error TS2322: 'string' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint '{}'.
227235
}
228236
}

tests/baselines/reference/assignmentCompatWithCallSignatures5.errors.txt

+4
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,13 @@ tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignme
55
Type '{ foo: U; bar: U; }' is not assignable to type '{ foo: T; bar: T; }'.
66
Types of property 'foo' are incompatible.
77
Type 'U' is not assignable to type 'T'.
8+
'U' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint '{}'.
89
tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithCallSignatures5.ts(55,1): error TS2322: Type '<T>(x: { a: T; b: T; }) => T[]' is not assignable to type '<U, V>(x: { a: U; b: V; }) => U[]'.
910
Types of parameters 'x' and 'x' are incompatible.
1011
Type '{ a: U; b: V; }' is not assignable to type '{ a: U; b: U; }'.
1112
Types of property 'b' are incompatible.
1213
Type 'V' is not assignable to type 'U'.
14+
'V' is assignable to the constraint of type 'U', but 'U' could be instantiated with a different subtype of constraint '{}'.
1315
tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithCallSignatures5.ts(58,1): error TS2322: Type '<T extends Base>(x: { a: T; b: T; }) => T[]' is not assignable to type '<U, V>(x: { a: U; b: V; }) => U[]'.
1416
Types of parameters 'x' and 'x' are incompatible.
1517
Type '{ a: U; b: V; }' is not assignable to type '{ a: Base; b: Base; }'.
@@ -79,6 +81,7 @@ tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignme
7981
!!! error TS2322: Type '{ foo: U; bar: U; }' is not assignable to type '{ foo: T; bar: T; }'.
8082
!!! error TS2322: Types of property 'foo' are incompatible.
8183
!!! error TS2322: Type 'U' is not assignable to type 'T'.
84+
!!! error TS2322: 'U' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint '{}'.
8285
var b15: <U, V>(x: { a: U; b: V; }) => U[];
8386
a15 = b15; // ok, T = U, T = V
8487
b15 = a15; // ok
@@ -88,6 +91,7 @@ tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignme
8891
!!! error TS2322: Type '{ a: U; b: V; }' is not assignable to type '{ a: U; b: U; }'.
8992
!!! error TS2322: Types of property 'b' are incompatible.
9093
!!! error TS2322: Type 'V' is not assignable to type 'U'.
94+
!!! error TS2322: 'V' is assignable to the constraint of type 'U', but 'U' could be instantiated with a different subtype of constraint '{}'.
9195
var b16: <T>(x: { a: T; b: T }) => T[];
9296
a15 = b16; // ok
9397
b15 = a16; // ok

tests/baselines/reference/assignmentCompatWithCallSignatures6.errors.txt

+2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignme
55
Type '{ foo: U; bar: U; }' is not assignable to type '{ foo: T; bar: T; }'.
66
Types of property 'foo' are incompatible.
77
Type 'U' is not assignable to type 'T'.
8+
'U' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint '{}'.
89
tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithCallSignatures6.ts(42,1): error TS2322: Type '<T extends Base>(x: { a: T; b: T; }) => T[]' is not assignable to type '<T>(x: { a: T; b: T; }) => T[]'.
910
Types of parameters 'x' and 'x' are incompatible.
1011
Type '{ a: T; b: T; }' is not assignable to type '{ a: Base; b: Base; }'.
@@ -61,6 +62,7 @@ tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignme
6162
!!! error TS2322: Type '{ foo: U; bar: U; }' is not assignable to type '{ foo: T; bar: T; }'.
6263
!!! error TS2322: Types of property 'foo' are incompatible.
6364
!!! error TS2322: Type 'U' is not assignable to type 'T'.
65+
!!! error TS2322: 'U' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint '{}'.
6466
var b16: <T>(x: { a: T; b: T }) => T[];
6567
x.a16 = b16;
6668
b16 = x.a16;

0 commit comments

Comments
 (0)