fix(31046): add new diagnostic message for incompatible constructor signature (#40073)

This commit is contained in:
Alexander T 2020-08-22 23:26:13 +03:00 committed by GitHub
parent 9569198df6
commit 2dd7a4bf93
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 208 additions and 13 deletions

View file

@ -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) {

View file

@ -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

View file

@ -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'.

View file

@ -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'.

View 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;

View 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))

View 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

View file

@ -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'.

View 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;

View 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))

View 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

View file

@ -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

View file

@ -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

View file

@ -0,0 +1,5 @@
class Foo {
constructor(x: number) {}
}
const foo: { new(): Foo } = Foo;

View file

@ -0,0 +1,7 @@
abstract class A {}
class B extends A {
constructor(x: number) {
super();
}
}
const b: typeof A = B;