fix(31046): add new diagnostic message for incompatible constructor signature (#40073)
This commit is contained in:
parent
9569198df6
commit
2dd7a4bf93
|
@ -17772,8 +17772,9 @@ namespace ts {
|
|||
let result = Ternary.True;
|
||||
const saveErrorInfo = captureErrorCalculationState();
|
||||
const incompatibleReporter = kind === SignatureKind.Construct ? reportIncompatibleConstructSignatureReturn : reportIncompatibleCallSignatureReturn;
|
||||
|
||||
if (getObjectFlags(source) & ObjectFlags.Instantiated && getObjectFlags(target) & ObjectFlags.Instantiated && source.symbol === target.symbol) {
|
||||
const sourceObjectFlags = getObjectFlags(source);
|
||||
const targetObjectFlags = getObjectFlags(target);
|
||||
if (sourceObjectFlags & ObjectFlags.Instantiated && targetObjectFlags & ObjectFlags.Instantiated && source.symbol === target.symbol) {
|
||||
// We have instantiations of the same anonymous type (which typically will be the type of a
|
||||
// method). Simply do a pairwise comparison of the signatures in the two signature lists instead
|
||||
// of the much more expensive N * M comparison matrix we explore below. We erase type parameters
|
||||
|
@ -17793,7 +17794,17 @@ namespace ts {
|
|||
// this regardless of the number of signatures, but the potential costs are prohibitive due
|
||||
// to the quadratic nature of the logic below.
|
||||
const eraseGenerics = relation === comparableRelation || !!compilerOptions.noStrictGenericChecks;
|
||||
result = signatureRelatedTo(sourceSignatures[0], targetSignatures[0], eraseGenerics, reportErrors, incompatibleReporter(sourceSignatures[0], targetSignatures[0]));
|
||||
const sourceSignature = first(sourceSignatures);
|
||||
const targetSignature = first(targetSignatures);
|
||||
result = signatureRelatedTo(sourceSignature, targetSignature, eraseGenerics, reportErrors, incompatibleReporter(sourceSignature, targetSignature));
|
||||
if (!result && reportErrors && kind === SignatureKind.Construct && (sourceObjectFlags & targetObjectFlags) &&
|
||||
(targetSignature.declaration?.kind === SyntaxKind.Constructor || sourceSignature.declaration?.kind === SyntaxKind.Constructor)) {
|
||||
const constructSignatureToString = (signature: Signature) =>
|
||||
signatureToString(signature, /*enclosingDeclaration*/ undefined, TypeFormatFlags.WriteArrowStyleSignature, kind);
|
||||
reportError(Diagnostics.Type_0_is_not_assignable_to_type_1, constructSignatureToString(sourceSignature), constructSignatureToString(targetSignature));
|
||||
reportError(Diagnostics.Types_of_construct_signatures_are_incompatible);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
else {
|
||||
outer: for (const t of targetSignatures) {
|
||||
|
|
|
@ -1686,6 +1686,10 @@
|
|||
"category": "Error",
|
||||
"code": 2418
|
||||
},
|
||||
"Types of construct signatures are incompatible.": {
|
||||
"category": "Error",
|
||||
"code": 2419
|
||||
},
|
||||
"Class '{0}' incorrectly implements interface '{1}'.": {
|
||||
"category": "Error",
|
||||
"code": 2420
|
||||
|
|
|
@ -6,8 +6,10 @@ tests/cases/compiler/assignmentCompatWithOverloads.ts(19,1): error TS2322: Type
|
|||
tests/cases/compiler/assignmentCompatWithOverloads.ts(21,1): error TS2322: Type '{ (x: string): string; (x: number): number; }' is not assignable to type '(s1: string) => number'.
|
||||
Type 'string' is not assignable to type 'number'.
|
||||
tests/cases/compiler/assignmentCompatWithOverloads.ts(30,1): error TS2322: Type 'typeof C' is not assignable to type 'new (x: number) => void'.
|
||||
Types of parameters 'x' and 'x' are incompatible.
|
||||
Type 'number' is not assignable to type 'string'.
|
||||
Types of construct signatures are incompatible.
|
||||
Type 'new (x: string) => C' is not assignable to type 'new (x: number) => void'.
|
||||
Types of parameters 'x' and 'x' are incompatible.
|
||||
Type 'number' is not assignable to type 'string'.
|
||||
|
||||
|
||||
==== tests/cases/compiler/assignmentCompatWithOverloads.ts (4 errors) ====
|
||||
|
@ -53,5 +55,7 @@ tests/cases/compiler/assignmentCompatWithOverloads.ts(30,1): error TS2322: Type
|
|||
d = C; // Error
|
||||
~
|
||||
!!! error TS2322: Type 'typeof C' is not assignable to type 'new (x: number) => void'.
|
||||
!!! error TS2322: Types of parameters 'x' and 'x' are incompatible.
|
||||
!!! error TS2322: Type 'number' is not assignable to type 'string'.
|
||||
!!! error TS2322: Types of construct signatures are incompatible.
|
||||
!!! error TS2322: Type 'new (x: string) => C' is not assignable to type 'new (x: number) => void'.
|
||||
!!! error TS2322: Types of parameters 'x' and 'x' are incompatible.
|
||||
!!! error TS2322: Type 'number' is not assignable to type 'string'.
|
|
@ -0,0 +1,16 @@
|
|||
tests/cases/compiler/assignmentCompatability44.ts(5,7): error TS2322: Type 'typeof Foo' is not assignable to type 'new () => Foo'.
|
||||
Types of construct signatures are incompatible.
|
||||
Type 'new (x: number) => Foo' is not assignable to type 'new () => Foo'.
|
||||
|
||||
|
||||
==== tests/cases/compiler/assignmentCompatability44.ts (1 errors) ====
|
||||
class Foo {
|
||||
constructor(x: number) {}
|
||||
}
|
||||
|
||||
const foo: { new(): Foo } = Foo;
|
||||
~~~
|
||||
!!! error TS2322: Type 'typeof Foo' is not assignable to type 'new () => Foo'.
|
||||
!!! error TS2322: Types of construct signatures are incompatible.
|
||||
!!! error TS2322: Type 'new (x: number) => Foo' is not assignable to type 'new () => Foo'.
|
||||
|
15
tests/baselines/reference/assignmentCompatability44.js
Normal file
15
tests/baselines/reference/assignmentCompatability44.js
Normal file
|
@ -0,0 +1,15 @@
|
|||
//// [assignmentCompatability44.ts]
|
||||
class Foo {
|
||||
constructor(x: number) {}
|
||||
}
|
||||
|
||||
const foo: { new(): Foo } = Foo;
|
||||
|
||||
|
||||
//// [assignmentCompatability44.js]
|
||||
var Foo = /** @class */ (function () {
|
||||
function Foo(x) {
|
||||
}
|
||||
return Foo;
|
||||
}());
|
||||
var foo = Foo;
|
13
tests/baselines/reference/assignmentCompatability44.symbols
Normal file
13
tests/baselines/reference/assignmentCompatability44.symbols
Normal file
|
@ -0,0 +1,13 @@
|
|||
=== tests/cases/compiler/assignmentCompatability44.ts ===
|
||||
class Foo {
|
||||
>Foo : Symbol(Foo, Decl(assignmentCompatability44.ts, 0, 0))
|
||||
|
||||
constructor(x: number) {}
|
||||
>x : Symbol(x, Decl(assignmentCompatability44.ts, 1, 16))
|
||||
}
|
||||
|
||||
const foo: { new(): Foo } = Foo;
|
||||
>foo : Symbol(foo, Decl(assignmentCompatability44.ts, 4, 5))
|
||||
>Foo : Symbol(Foo, Decl(assignmentCompatability44.ts, 0, 0))
|
||||
>Foo : Symbol(Foo, Decl(assignmentCompatability44.ts, 0, 0))
|
||||
|
12
tests/baselines/reference/assignmentCompatability44.types
Normal file
12
tests/baselines/reference/assignmentCompatability44.types
Normal file
|
@ -0,0 +1,12 @@
|
|||
=== tests/cases/compiler/assignmentCompatability44.ts ===
|
||||
class Foo {
|
||||
>Foo : Foo
|
||||
|
||||
constructor(x: number) {}
|
||||
>x : number
|
||||
}
|
||||
|
||||
const foo: { new(): Foo } = Foo;
|
||||
>foo : new () => Foo
|
||||
>Foo : typeof Foo
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
tests/cases/compiler/assignmentCompatability45.ts(7,7): error TS2322: Type 'typeof B' is not assignable to type 'typeof A'.
|
||||
Types of construct signatures are incompatible.
|
||||
Type 'new (x: number) => B' is not assignable to type 'new () => A'.
|
||||
|
||||
|
||||
==== tests/cases/compiler/assignmentCompatability45.ts (1 errors) ====
|
||||
abstract class A {}
|
||||
class B extends A {
|
||||
constructor(x: number) {
|
||||
super();
|
||||
}
|
||||
}
|
||||
const b: typeof A = B;
|
||||
~
|
||||
!!! error TS2322: Type 'typeof B' is not assignable to type 'typeof A'.
|
||||
!!! error TS2322: Types of construct signatures are incompatible.
|
||||
!!! error TS2322: Type 'new (x: number) => B' is not assignable to type 'new () => A'.
|
||||
|
37
tests/baselines/reference/assignmentCompatability45.js
Normal file
37
tests/baselines/reference/assignmentCompatability45.js
Normal file
|
@ -0,0 +1,37 @@
|
|||
//// [assignmentCompatability45.ts]
|
||||
abstract class A {}
|
||||
class B extends A {
|
||||
constructor(x: number) {
|
||||
super();
|
||||
}
|
||||
}
|
||||
const b: typeof A = B;
|
||||
|
||||
|
||||
//// [assignmentCompatability45.js]
|
||||
var __extends = (this && this.__extends) || (function () {
|
||||
var extendStatics = function (d, b) {
|
||||
extendStatics = Object.setPrototypeOf ||
|
||||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
||||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
|
||||
return extendStatics(d, b);
|
||||
};
|
||||
return function (d, b) {
|
||||
extendStatics(d, b);
|
||||
function __() { this.constructor = d; }
|
||||
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
||||
};
|
||||
})();
|
||||
var A = /** @class */ (function () {
|
||||
function A() {
|
||||
}
|
||||
return A;
|
||||
}());
|
||||
var B = /** @class */ (function (_super) {
|
||||
__extends(B, _super);
|
||||
function B(x) {
|
||||
return _super.call(this) || this;
|
||||
}
|
||||
return B;
|
||||
}(A));
|
||||
var b = B;
|
20
tests/baselines/reference/assignmentCompatability45.symbols
Normal file
20
tests/baselines/reference/assignmentCompatability45.symbols
Normal file
|
@ -0,0 +1,20 @@
|
|||
=== tests/cases/compiler/assignmentCompatability45.ts ===
|
||||
abstract class A {}
|
||||
>A : Symbol(A, Decl(assignmentCompatability45.ts, 0, 0))
|
||||
|
||||
class B extends A {
|
||||
>B : Symbol(B, Decl(assignmentCompatability45.ts, 0, 19))
|
||||
>A : Symbol(A, Decl(assignmentCompatability45.ts, 0, 0))
|
||||
|
||||
constructor(x: number) {
|
||||
>x : Symbol(x, Decl(assignmentCompatability45.ts, 2, 16))
|
||||
|
||||
super();
|
||||
>super : Symbol(A, Decl(assignmentCompatability45.ts, 0, 0))
|
||||
}
|
||||
}
|
||||
const b: typeof A = B;
|
||||
>b : Symbol(b, Decl(assignmentCompatability45.ts, 6, 5))
|
||||
>A : Symbol(A, Decl(assignmentCompatability45.ts, 0, 0))
|
||||
>B : Symbol(B, Decl(assignmentCompatability45.ts, 0, 19))
|
||||
|
21
tests/baselines/reference/assignmentCompatability45.types
Normal file
21
tests/baselines/reference/assignmentCompatability45.types
Normal file
|
@ -0,0 +1,21 @@
|
|||
=== tests/cases/compiler/assignmentCompatability45.ts ===
|
||||
abstract class A {}
|
||||
>A : A
|
||||
|
||||
class B extends A {
|
||||
>B : B
|
||||
>A : A
|
||||
|
||||
constructor(x: number) {
|
||||
>x : number
|
||||
|
||||
super();
|
||||
>super() : void
|
||||
>super : typeof A
|
||||
}
|
||||
}
|
||||
const b: typeof A = B;
|
||||
>b : typeof A
|
||||
>A : typeof A
|
||||
>B : typeof B
|
||||
|
|
@ -1,5 +1,9 @@
|
|||
tests/cases/compiler/classSideInheritance3.ts(16,5): error TS2322: Type 'typeof B' is not assignable to type 'typeof A'.
|
||||
Types of construct signatures are incompatible.
|
||||
Type 'new (x: string, data: string) => B' is not assignable to type 'new (x: string) => A'.
|
||||
tests/cases/compiler/classSideInheritance3.ts(17,5): error TS2322: Type 'typeof B' is not assignable to type 'new (x: string) => A'.
|
||||
Types of construct signatures are incompatible.
|
||||
Type 'new (x: string, data: string) => B' is not assignable to type 'new (x: string) => A'.
|
||||
|
||||
|
||||
==== tests/cases/compiler/classSideInheritance3.ts (2 errors) ====
|
||||
|
@ -21,7 +25,11 @@ tests/cases/compiler/classSideInheritance3.ts(17,5): error TS2322: Type 'typeof
|
|||
var r1: typeof A = B; // error
|
||||
~~
|
||||
!!! error TS2322: Type 'typeof B' is not assignable to type 'typeof A'.
|
||||
!!! error TS2322: Types of construct signatures are incompatible.
|
||||
!!! error TS2322: Type 'new (x: string, data: string) => B' is not assignable to type 'new (x: string) => A'.
|
||||
var r2: new (x: string) => A = B; // error
|
||||
~~
|
||||
!!! error TS2322: Type 'typeof B' is not assignable to type 'new (x: string) => A'.
|
||||
!!! error TS2322: Types of construct signatures are incompatible.
|
||||
!!! error TS2322: Type 'new (x: string, data: string) => B' is not assignable to type 'new (x: string) => A'.
|
||||
var r3: typeof A = C; // ok
|
|
@ -45,9 +45,11 @@ tests/cases/conformance/functions/strictBindCallApply1.ts(62,11): error TS2769:
|
|||
Argument of type 'number' is not assignable to parameter of type 'string'.
|
||||
Overload 2 of 6, '(this: new (...args: (10 | 20)[]) => C, thisArg: any, ...args: (10 | 20)[]): new (...args: (10 | 20)[]) => C', gave the following error.
|
||||
The 'this' context of type 'typeof C' is not assignable to method's 'this' of type 'new (...args: (10 | 20)[]) => C'.
|
||||
Types of parameters 'b' and 'args' are incompatible.
|
||||
Type 'number' is not assignable to type 'string'.
|
||||
Type 'number' is not assignable to type 'string'.
|
||||
Types of construct signatures are incompatible.
|
||||
Type 'new (a: number, b: string) => C' is not assignable to type 'new (...args: (10 | 20)[]) => C'.
|
||||
Types of parameters 'b' and 'args' are incompatible.
|
||||
Type 'number' is not assignable to type 'string'.
|
||||
Type 'number' is not assignable to type 'string'.
|
||||
tests/cases/conformance/functions/strictBindCallApply1.ts(65,3): error TS2554: Expected 3 arguments, but got 2.
|
||||
tests/cases/conformance/functions/strictBindCallApply1.ts(66,15): error TS2345: Argument of type 'number' is not assignable to parameter of type 'string'.
|
||||
tests/cases/conformance/functions/strictBindCallApply1.ts(67,24): error TS2554: Expected 3 arguments, but got 4.
|
||||
|
@ -186,9 +188,11 @@ tests/cases/conformance/functions/strictBindCallApply1.ts(72,12): error TS2345:
|
|||
!!! error TS2769: Argument of type 'number' is not assignable to parameter of type 'string'.
|
||||
!!! error TS2769: Overload 2 of 6, '(this: new (...args: (10 | 20)[]) => C, thisArg: any, ...args: (10 | 20)[]): new (...args: (10 | 20)[]) => C', gave the following error.
|
||||
!!! error TS2769: The 'this' context of type 'typeof C' is not assignable to method's 'this' of type 'new (...args: (10 | 20)[]) => C'.
|
||||
!!! error TS2769: Types of parameters 'b' and 'args' are incompatible.
|
||||
!!! error TS2769: Type 'number' is not assignable to type 'string'.
|
||||
!!! error TS2769: Type 'number' is not assignable to type 'string'.
|
||||
!!! error TS2769: Types of construct signatures are incompatible.
|
||||
!!! error TS2769: Type 'new (a: number, b: string) => C' is not assignable to type 'new (...args: (10 | 20)[]) => C'.
|
||||
!!! error TS2769: Types of parameters 'b' and 'args' are incompatible.
|
||||
!!! error TS2769: Type 'number' is not assignable to type 'string'.
|
||||
!!! error TS2769: Type 'number' is not assignable to type 'string'.
|
||||
|
||||
C.call(c, 10, "hello");
|
||||
C.call(c, 10); // Error
|
||||
|
|
5
tests/cases/compiler/assignmentCompatability44.ts
Normal file
5
tests/cases/compiler/assignmentCompatability44.ts
Normal file
|
@ -0,0 +1,5 @@
|
|||
class Foo {
|
||||
constructor(x: number) {}
|
||||
}
|
||||
|
||||
const foo: { new(): Foo } = Foo;
|
7
tests/cases/compiler/assignmentCompatability45.ts
Normal file
7
tests/cases/compiler/assignmentCompatability45.ts
Normal file
|
@ -0,0 +1,7 @@
|
|||
abstract class A {}
|
||||
class B extends A {
|
||||
constructor(x: number) {
|
||||
super();
|
||||
}
|
||||
}
|
||||
const b: typeof A = B;
|
Loading…
Reference in a new issue