Skip to content

Commit 886079b

Browse files
committed
fix(31046): add new diagnostic message for incompatible constructor signature
1 parent 610fa28 commit 886079b

29 files changed

+1096
-553
lines changed

src/compiler/checker.ts

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17715,8 +17715,9 @@ namespace ts {
1771517715
let result = Ternary.True;
1771617716
const saveErrorInfo = captureErrorCalculationState();
1771717717
const incompatibleReporter = kind === SignatureKind.Construct ? reportIncompatibleConstructSignatureReturn : reportIncompatibleCallSignatureReturn;
17718-
17719-
if (getObjectFlags(source) & ObjectFlags.Instantiated && getObjectFlags(target) & ObjectFlags.Instantiated && source.symbol === target.symbol) {
17718+
const sourceObjectFlags = getObjectFlags(source);
17719+
const targetObjectFlags = getObjectFlags(target);
17720+
if (sourceObjectFlags & ObjectFlags.Instantiated && targetObjectFlags & ObjectFlags.Instantiated && source.symbol === target.symbol) {
1772017721
// We have instantiations of the same anonymous type (which typically will be the type of a
1772117722
// method). Simply do a pairwise comparison of the signatures in the two signature lists instead
1772217723
// of the much more expensive N * M comparison matrix we explore below. We erase type parameters
@@ -17736,7 +17737,19 @@ namespace ts {
1773617737
// this regardless of the number of signatures, but the potential costs are prohibitive due
1773717738
// to the quadratic nature of the logic below.
1773817739
const eraseGenerics = relation === comparableRelation || !!compilerOptions.noStrictGenericChecks;
17739-
result = signatureRelatedTo(sourceSignatures[0], targetSignatures[0], eraseGenerics, reportErrors, incompatibleReporter(sourceSignatures[0], targetSignatures[0]));
17740+
const sourceSignature = first(sourceSignatures);
17741+
const targetSignature = first(targetSignatures);
17742+
result = signatureRelatedTo(sourceSignature, targetSignature, eraseGenerics, reportErrors, incompatibleReporter(sourceSignature, targetSignature));
17743+
if (!result && reportErrors && kind === SignatureKind.Construct && (sourceObjectFlags & targetObjectFlags)) {
17744+
const declaration = targetSignature.declaration || sourceSignature.declaration;
17745+
if (declaration && (isConstructorDeclaration(declaration) || isConstructSignatureDeclaration(declaration) || isConstructorTypeNode(declaration))) {
17746+
const constructSignatureToString = (signature: Signature) =>
17747+
signatureToString(signature, /*enclosingDeclaration*/ undefined, TypeFormatFlags.WriteArrowStyleSignature, kind);
17748+
reportError(Diagnostics.Type_0_is_not_assignable_to_type_1, constructSignatureToString(sourceSignature), constructSignatureToString(targetSignature));
17749+
reportError(Diagnostics.Types_of_construct_signature_are_incompatible);
17750+
return result;
17751+
}
17752+
}
1774017753
}
1774117754
else {
1774217755
outer: for (const t of targetSignatures) {

src/compiler/diagnosticMessages.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1686,6 +1686,10 @@
16861686
"category": "Error",
16871687
"code": 2418
16881688
},
1689+
"Types of construct signature are incompatible.": {
1690+
"category": "Error",
1691+
"code": 2419
1692+
},
16891693
"Class '{0}' incorrectly implements interface '{1}'.": {
16901694
"category": "Error",
16911695
"code": 2420

tests/baselines/reference/assignmentCompatWithConstructSignatures3.errors.txt

Lines changed: 154 additions & 98 deletions
Large diffs are not rendered by default.

tests/baselines/reference/assignmentCompatWithConstructSignatures4.errors.txt

Lines changed: 156 additions & 110 deletions
Large diffs are not rendered by default.

tests/baselines/reference/assignmentCompatWithConstructSignatures5.errors.txt

Lines changed: 48 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,30 @@
1-
tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithConstructSignatures5.ts(40,1): error TS2322: Type 'new <T>(x: T) => void' is not assignable to type 'new <T>(x: T) => T'.
2-
Type 'void' is not assignable to type 'T'.
3-
'T' could be instantiated with an arbitrary type which could be unrelated to 'void'.
1+
tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithConstructSignatures5.ts(40,1): error TS2419: Types of construct signature are incompatible.
2+
Type 'new <T>(x: T) => void' is not assignable to type 'new <T>(x: T) => T'.
3+
Type 'void' is not assignable to type 'T'.
4+
'T' could be instantiated with an arbitrary type which could be unrelated to 'void'.
45
tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithConstructSignatures5.ts(52,1): error TS2322: Type 'new <T>(x: { foo: T; }, y: { foo: T; bar: T; }) => Base' is not assignable to type 'new <T, U>(x: { foo: T; }, y: { foo: U; bar: U; }) => Base'.
5-
Types of parameters 'y' and 'y' are incompatible.
6-
Type '{ foo: U; bar: U; }' is not assignable to type '{ foo: T; bar: T; }'.
7-
Types of property 'foo' are incompatible.
8-
Type 'U' is not assignable to type 'T'.
9-
'T' could be instantiated with an arbitrary type which could be unrelated to 'U'.
6+
Types of construct signature are incompatible.
7+
Type 'new <T>(x: { foo: T; }, y: { foo: T; bar: T; }) => Base' is not assignable to type 'new <T, U>(x: { foo: T; }, y: { foo: U; bar: U; }) => Base'.
8+
Types of parameters 'y' and 'y' are incompatible.
9+
Type '{ foo: U; bar: U; }' is not assignable to type '{ foo: T; bar: T; }'.
10+
Types of property 'foo' are incompatible.
11+
Type 'U' is not assignable to type 'T'.
12+
'T' could be instantiated with an arbitrary type which could be unrelated to 'U'.
1013
tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithConstructSignatures5.ts(55,1): error TS2322: Type 'new <T>(x: { a: T; b: T; }) => T[]' is not assignable to type 'new <U, V>(x: { a: U; b: V; }) => U[]'.
11-
Types of parameters 'x' and 'x' are incompatible.
12-
Type '{ a: U; b: V; }' is not assignable to type '{ a: U; b: U; }'.
13-
Types of property 'b' are incompatible.
14-
Type 'V' is not assignable to type 'U'.
15-
'U' could be instantiated with an arbitrary type which could be unrelated to 'V'.
14+
Types of construct signature are incompatible.
15+
Type 'new <T>(x: { a: T; b: T; }) => T[]' is not assignable to type 'new <U, V>(x: { a: U; b: V; }) => U[]'.
16+
Types of parameters 'x' and 'x' are incompatible.
17+
Type '{ a: U; b: V; }' is not assignable to type '{ a: U; b: U; }'.
18+
Types of property 'b' are incompatible.
19+
Type 'V' is not assignable to type 'U'.
20+
'U' could be instantiated with an arbitrary type which could be unrelated to 'V'.
1621
tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithConstructSignatures5.ts(58,1): error TS2322: Type 'new <T extends Base>(x: { a: T; b: T; }) => T[]' is not assignable to type 'new <U, V>(x: { a: U; b: V; }) => U[]'.
17-
Types of parameters 'x' and 'x' are incompatible.
18-
Type '{ a: U; b: V; }' is not assignable to type '{ a: Base; b: Base; }'.
19-
Types of property 'a' are incompatible.
20-
Type 'U' is not assignable to type 'Base'.
22+
Types of construct signature are incompatible.
23+
Type 'new <T extends Base>(x: { a: T; b: T; }) => T[]' is not assignable to type 'new <U, V>(x: { a: U; b: V; }) => U[]'.
24+
Types of parameters 'x' and 'x' are incompatible.
25+
Type '{ a: U; b: V; }' is not assignable to type '{ a: Base; b: Base; }'.
26+
Types of property 'a' are incompatible.
27+
Type 'U' is not assignable to type 'Base'.
2128

2229

2330
==== tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithConstructSignatures5.ts (4 errors) ====
@@ -62,9 +69,10 @@ tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignme
6269
a3 = b3; // ok
6370
b3 = a3; // ok
6471
~~
65-
!!! error TS2322: Type 'new <T>(x: T) => void' is not assignable to type 'new <T>(x: T) => T'.
66-
!!! error TS2322: Type 'void' is not assignable to type 'T'.
67-
!!! error TS2322: 'T' could be instantiated with an arbitrary type which could be unrelated to 'void'.
72+
!!! error TS2419: Types of construct signature are incompatible.
73+
!!! error TS2419: Type 'new <T>(x: T) => void' is not assignable to type 'new <T>(x: T) => T'.
74+
!!! error TS2419: Type 'void' is not assignable to type 'T'.
75+
!!! error TS2419: 'T' could be instantiated with an arbitrary type which could be unrelated to 'void'.
6876
var b4: new <T, U>(x: T, y: U) => string;
6977
a4 = b4; // ok
7078
b4 = a4; // ok
@@ -79,30 +87,36 @@ tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignme
7987
b11 = a11; // ok
8088
~~~
8189
!!! error TS2322: Type 'new <T>(x: { foo: T; }, y: { foo: T; bar: T; }) => Base' is not assignable to type 'new <T, U>(x: { foo: T; }, y: { foo: U; bar: U; }) => Base'.
82-
!!! error TS2322: Types of parameters 'y' and 'y' are incompatible.
83-
!!! error TS2322: Type '{ foo: U; bar: U; }' is not assignable to type '{ foo: T; bar: T; }'.
84-
!!! error TS2322: Types of property 'foo' are incompatible.
85-
!!! error TS2322: Type 'U' is not assignable to type 'T'.
86-
!!! error TS2322: 'T' could be instantiated with an arbitrary type which could be unrelated to 'U'.
90+
!!! error TS2322: Types of construct signature are incompatible.
91+
!!! error TS2322: Type 'new <T>(x: { foo: T; }, y: { foo: T; bar: T; }) => Base' is not assignable to type 'new <T, U>(x: { foo: T; }, y: { foo: U; bar: U; }) => Base'.
92+
!!! error TS2322: Types of parameters 'y' and 'y' are incompatible.
93+
!!! error TS2322: Type '{ foo: U; bar: U; }' is not assignable to type '{ foo: T; bar: T; }'.
94+
!!! error TS2322: Types of property 'foo' are incompatible.
95+
!!! error TS2322: Type 'U' is not assignable to type 'T'.
96+
!!! error TS2322: 'T' could be instantiated with an arbitrary type which could be unrelated to 'U'.
8797
var b15: new <U, V>(x: { a: U; b: V; }) => U[];
8898
a15 = b15; // ok
8999
b15 = a15; // ok
90100
~~~
91101
!!! error TS2322: Type 'new <T>(x: { a: T; b: T; }) => T[]' is not assignable to type 'new <U, V>(x: { a: U; b: V; }) => U[]'.
92-
!!! error TS2322: Types of parameters 'x' and 'x' are incompatible.
93-
!!! error TS2322: Type '{ a: U; b: V; }' is not assignable to type '{ a: U; b: U; }'.
94-
!!! error TS2322: Types of property 'b' are incompatible.
95-
!!! error TS2322: Type 'V' is not assignable to type 'U'.
96-
!!! error TS2322: 'U' could be instantiated with an arbitrary type which could be unrelated to 'V'.
102+
!!! error TS2322: Types of construct signature are incompatible.
103+
!!! error TS2322: Type 'new <T>(x: { a: T; b: T; }) => T[]' is not assignable to type 'new <U, V>(x: { a: U; b: V; }) => U[]'.
104+
!!! error TS2322: Types of parameters 'x' and 'x' are incompatible.
105+
!!! error TS2322: Type '{ a: U; b: V; }' is not assignable to type '{ a: U; b: U; }'.
106+
!!! error TS2322: Types of property 'b' are incompatible.
107+
!!! error TS2322: Type 'V' is not assignable to type 'U'.
108+
!!! error TS2322: 'U' could be instantiated with an arbitrary type which could be unrelated to 'V'.
97109
var b16: new <T>(x: { a: T; b: T }) => T[];
98110
a15 = b16; // ok
99111
b15 = a16; // ok
100112
~~~
101113
!!! error TS2322: Type 'new <T extends Base>(x: { a: T; b: T; }) => T[]' is not assignable to type 'new <U, V>(x: { a: U; b: V; }) => U[]'.
102-
!!! error TS2322: Types of parameters 'x' and 'x' are incompatible.
103-
!!! error TS2322: Type '{ a: U; b: V; }' is not assignable to type '{ a: Base; b: Base; }'.
104-
!!! error TS2322: Types of property 'a' are incompatible.
105-
!!! error TS2322: Type 'U' is not assignable to type 'Base'.
114+
!!! error TS2322: Types of construct signature are incompatible.
115+
!!! error TS2322: Type 'new <T extends Base>(x: { a: T; b: T; }) => T[]' is not assignable to type 'new <U, V>(x: { a: U; b: V; }) => U[]'.
116+
!!! error TS2322: Types of parameters 'x' and 'x' are incompatible.
117+
!!! error TS2322: Type '{ a: U; b: V; }' is not assignable to type '{ a: Base; b: Base; }'.
118+
!!! error TS2322: Types of property 'a' are incompatible.
119+
!!! error TS2322: Type 'U' is not assignable to type 'Base'.
106120
var b17: new <T>(x: new (a: T) => T) => T[];
107121
a17 = b17; // ok
108122
b17 = a17; // ok

tests/baselines/reference/assignmentCompatWithConstructSignatures6.errors.txt

Lines changed: 34 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,22 @@
1-
tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithConstructSignatures6.ts(30,1): error TS2322: Type 'new <T>(x: T) => void' is not assignable to type 'new <T>(x: T) => T'.
2-
Type 'void' is not assignable to type 'T'.
3-
'T' could be instantiated with an arbitrary type which could be unrelated to 'void'.
1+
tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithConstructSignatures6.ts(30,1): error TS2419: Types of construct signature are incompatible.
2+
Type 'new <T>(x: T) => void' is not assignable to type 'new <T>(x: T) => T'.
3+
Type 'void' is not assignable to type 'T'.
4+
'T' could be instantiated with an arbitrary type which could be unrelated to 'void'.
45
tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithConstructSignatures6.ts(39,1): error TS2322: Type 'new <T>(x: { foo: T; }, y: { foo: T; bar: T; }) => Base' is not assignable to type 'new <T, U>(x: { foo: T; }, y: { foo: U; bar: U; }) => Base'.
5-
Types of parameters 'y' and 'y' are incompatible.
6-
Type '{ foo: U; bar: U; }' is not assignable to type '{ foo: T; bar: T; }'.
7-
Types of property 'foo' are incompatible.
8-
Type 'U' is not assignable to type 'T'.
9-
'T' could be instantiated with an arbitrary type which could be unrelated to 'U'.
6+
Types of construct signature are incompatible.
7+
Type 'new <T>(x: { foo: T; }, y: { foo: T; bar: T; }) => Base' is not assignable to type 'new <T, U>(x: { foo: T; }, y: { foo: U; bar: U; }) => Base'.
8+
Types of parameters 'y' and 'y' are incompatible.
9+
Type '{ foo: U; bar: U; }' is not assignable to type '{ foo: T; bar: T; }'.
10+
Types of property 'foo' are incompatible.
11+
Type 'U' is not assignable to type 'T'.
12+
'T' could be instantiated with an arbitrary type which could be unrelated to 'U'.
1013
tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithConstructSignatures6.ts(42,1): error TS2322: Type 'new <T extends Base>(x: { a: T; b: T; }) => T[]' is not assignable to type 'new <T>(x: { a: T; b: T; }) => T[]'.
11-
Types of parameters 'x' and 'x' are incompatible.
12-
Type '{ a: T; b: T; }' is not assignable to type '{ a: Base; b: Base; }'.
13-
Types of property 'a' are incompatible.
14-
Type 'T' is not assignable to type 'Base'.
14+
Types of construct signature are incompatible.
15+
Type 'new <T extends Base>(x: { a: T; b: T; }) => T[]' is not assignable to type 'new <T>(x: { a: T; b: T; }) => T[]'.
16+
Types of parameters 'x' and 'x' are incompatible.
17+
Type '{ a: T; b: T; }' is not assignable to type '{ a: Base; b: Base; }'.
18+
Types of property 'a' are incompatible.
19+
Type 'T' is not assignable to type 'Base'.
1520

1621

1722
==== tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithConstructSignatures6.ts (3 errors) ====
@@ -46,9 +51,10 @@ tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignme
4651
x.a3 = b3;
4752
b3 = x.a3;
4853
~~
49-
!!! error TS2322: Type 'new <T>(x: T) => void' is not assignable to type 'new <T>(x: T) => T'.
50-
!!! error TS2322: Type 'void' is not assignable to type 'T'.
51-
!!! error TS2322: 'T' could be instantiated with an arbitrary type which could be unrelated to 'void'.
54+
!!! error TS2419: Types of construct signature are incompatible.
55+
!!! error TS2419: Type 'new <T>(x: T) => void' is not assignable to type 'new <T>(x: T) => T'.
56+
!!! error TS2419: Type 'void' is not assignable to type 'T'.
57+
!!! error TS2419: 'T' could be instantiated with an arbitrary type which could be unrelated to 'void'.
5258
var b4: new <T, U>(x: T, y: U) => string;
5359
x.a4 = b4;
5460
b4 = x.a4;
@@ -60,17 +66,21 @@ tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignme
6066
b11 = x.a11;
6167
~~~
6268
!!! error TS2322: Type 'new <T>(x: { foo: T; }, y: { foo: T; bar: T; }) => Base' is not assignable to type 'new <T, U>(x: { foo: T; }, y: { foo: U; bar: U; }) => Base'.
63-
!!! error TS2322: Types of parameters 'y' and 'y' are incompatible.
64-
!!! error TS2322: Type '{ foo: U; bar: U; }' is not assignable to type '{ foo: T; bar: T; }'.
65-
!!! error TS2322: Types of property 'foo' are incompatible.
66-
!!! error TS2322: Type 'U' is not assignable to type 'T'.
67-
!!! error TS2322: 'T' could be instantiated with an arbitrary type which could be unrelated to 'U'.
69+
!!! error TS2322: Types of construct signature are incompatible.
70+
!!! error TS2322: Type 'new <T>(x: { foo: T; }, y: { foo: T; bar: T; }) => Base' is not assignable to type 'new <T, U>(x: { foo: T; }, y: { foo: U; bar: U; }) => Base'.
71+
!!! error TS2322: Types of parameters 'y' and 'y' are incompatible.
72+
!!! error TS2322: Type '{ foo: U; bar: U; }' is not assignable to type '{ foo: T; bar: T; }'.
73+
!!! error TS2322: Types of property 'foo' are incompatible.
74+
!!! error TS2322: Type 'U' is not assignable to type 'T'.
75+
!!! error TS2322: 'T' could be instantiated with an arbitrary type which could be unrelated to 'U'.
6876
var b16: new <T>(x: { a: T; b: T }) => T[];
6977
x.a16 = b16;
7078
b16 = x.a16;
7179
~~~
7280
!!! error TS2322: Type 'new <T extends Base>(x: { a: T; b: T; }) => T[]' is not assignable to type 'new <T>(x: { a: T; b: T; }) => T[]'.
73-
!!! error TS2322: Types of parameters 'x' and 'x' are incompatible.
74-
!!! error TS2322: Type '{ a: T; b: T; }' is not assignable to type '{ a: Base; b: Base; }'.
75-
!!! error TS2322: Types of property 'a' are incompatible.
76-
!!! error TS2322: Type 'T' is not assignable to type 'Base'.
81+
!!! error TS2322: Types of construct signature are incompatible.
82+
!!! error TS2322: Type 'new <T extends Base>(x: { a: T; b: T; }) => T[]' is not assignable to type 'new <T>(x: { a: T; b: T; }) => T[]'.
83+
!!! error TS2322: Types of parameters 'x' and 'x' are incompatible.
84+
!!! error TS2322: Type '{ a: T; b: T; }' is not assignable to type '{ a: Base; b: Base; }'.
85+
!!! error TS2322: Types of property 'a' are incompatible.
86+
!!! error TS2322: Type 'T' is not assignable to type 'Base'.

0 commit comments

Comments
 (0)