Skip to content

fix #19220: polish arity error message #19405

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 31 additions & 15 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16272,23 +16272,39 @@ namespace ts {
diagnostics.add(createDiagnosticForNode(node, Diagnostics.Expected_0_type_arguments_but_got_1, paramCount, typeArguments.length));
}
else if (args) {
let min = Number.POSITIVE_INFINITY;
let max = Number.NEGATIVE_INFINITY;
for (const sig of signatures) {
min = Math.min(min, sig.minArgumentCount);
max = Math.max(max, sig.parameters.length);
}
const hasRestParameter = some(signatures, sig => sig.hasRestParameter);
const hasSpreadArgument = getSpreadArgumentIndex(args) > -1;
const paramCount = hasRestParameter ? min :
min < max ? min + "-" + max :
min;
const argCount = args.length - (hasSpreadArgument ? 1 : 0);
const error = hasRestParameter && hasSpreadArgument ? Diagnostics.Expected_at_least_0_arguments_but_got_a_minimum_of_1 :
hasRestParameter ? Diagnostics.Expected_at_least_0_arguments_but_got_1 :
hasSpreadArgument ? Diagnostics.Expected_0_arguments_but_got_a_minimum_of_1 :
Diagnostics.Expected_0_arguments_but_got_1;
diagnostics.add(createDiagnosticForNode(node, error, paramCount, argCount));
// polish error message for overloaded call without spread argument
if (!hasSpreadArgument && signatures.length > 1) {
// compute arity bound to guess most matching overload
let upper = Number.POSITIVE_INFINITY;
let lower = Number.NEGATIVE_INFINITY;
for (const sig of signatures) {
const minParam = sig.minArgumentCount;
const maxParam = sig.parameters.length;
upper = minParam > argCount ? Math.min(upper, minParam) : upper;
lower = maxParam < argCount ? Math.max(lower, maxParam) : lower;
}
const paramText = upper !== Number.POSITIVE_INFINITY && lower !== Number.NEGATIVE_INFINITY && upper !== lower ? `either ${lower} or ${upper}` :
upper !== Number.POSITIVE_INFINITY ? upper : lower;
diagnostics.add(
createDiagnosticForNode(node, Diagnostics.No_overload_expects_0_arguments_The_most_matching_overloads_expect_1_arguments, argCount, paramText));
}
else {
let min = Number.POSITIVE_INFINITY;
let max = Number.NEGATIVE_INFINITY;
for (const sig of signatures) {
min = Math.min(min, sig.minArgumentCount);
max = Math.max(max, sig.parameters.length);
}
const hasRestParameter = some(signatures, sig => sig.hasRestParameter);
const error = hasRestParameter && hasSpreadArgument ? Diagnostics.Expected_at_least_0_arguments_but_got_a_minimum_of_1 :
hasRestParameter ? Diagnostics.Expected_at_least_0_arguments_but_got_1 :
hasSpreadArgument ? Diagnostics.Expected_0_arguments_but_got_a_minimum_of_1 :
Diagnostics.Expected_0_arguments_but_got_1;
const paramCount = (hasRestParameter || min >= max) ? min : min + "-" + max;
diagnostics.add(createDiagnosticForNode(node, error, paramCount, argCount));
}
}
else if (fallbackError) {
diagnostics.add(createDiagnosticForNode(node, fallbackError));
Expand Down
8 changes: 8 additions & 0 deletions src/compiler/diagnosticMessages.json
Original file line number Diff line number Diff line change
Expand Up @@ -2228,6 +2228,14 @@
"category": "Error",
"code": 2716
},
"Type parameter '{0}' has a circular default.": {
"category": "Error",
"code": 2716
},
"No overload expects {0} arguments. The most matching overloads expect {1} arguments.": {
"category": "Error",
"code": 2717
},

"Import declaration '{0}' is using private name '{1}'.": {
"category": "Error",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
tests/cases/compiler/blockScopedSameNameFunctionDeclarationES5.ts(3,18): error TS2393: Duplicate function implementation.
tests/cases/compiler/blockScopedSameNameFunctionDeclarationES5.ts(5,9): error TS2554: Expected 0 arguments, but got 1.
tests/cases/compiler/blockScopedSameNameFunctionDeclarationES5.ts(5,9): error TS2717: No overload expects 1 arguments. The most matching overloads expect 0 arguments.
tests/cases/compiler/blockScopedSameNameFunctionDeclarationES5.ts(8,18): error TS2393: Duplicate function implementation.
tests/cases/compiler/blockScopedSameNameFunctionDeclarationES5.ts(10,9): error TS2554: Expected 0 arguments, but got 1.
tests/cases/compiler/blockScopedSameNameFunctionDeclarationES5.ts(12,5): error TS2554: Expected 0 arguments, but got 1.
tests/cases/compiler/blockScopedSameNameFunctionDeclarationES5.ts(10,9): error TS2717: No overload expects 1 arguments. The most matching overloads expect 0 arguments.
tests/cases/compiler/blockScopedSameNameFunctionDeclarationES5.ts(12,5): error TS2717: No overload expects 1 arguments. The most matching overloads expect 0 arguments.
tests/cases/compiler/blockScopedSameNameFunctionDeclarationES5.ts(16,1): error TS2554: Expected 1 arguments, but got 0.


Expand All @@ -15,7 +15,7 @@ tests/cases/compiler/blockScopedSameNameFunctionDeclarationES5.ts(16,1): error T
foo();
foo(10); // not ok
~~~~~~~
!!! error TS2554: Expected 0 arguments, but got 1.
!!! error TS2717: No overload expects 1 arguments. The most matching overloads expect 0 arguments.
}
else {
function foo() { } // duplicate function
Expand All @@ -24,11 +24,11 @@ tests/cases/compiler/blockScopedSameNameFunctionDeclarationES5.ts(16,1): error T
foo();
foo(10); // not ok
~~~~~~~
!!! error TS2554: Expected 0 arguments, but got 1.
!!! error TS2717: No overload expects 1 arguments. The most matching overloads expect 0 arguments.
}
foo(10); // not ok
~~~~~~~
!!! error TS2554: Expected 0 arguments, but got 1.
!!! error TS2717: No overload expects 1 arguments. The most matching overloads expect 0 arguments.
foo();
}
foo(10);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
tests/cases/compiler/blockScopedSameNameFunctionDeclarationES6.ts(3,18): error TS2393: Duplicate function implementation.
tests/cases/compiler/blockScopedSameNameFunctionDeclarationES6.ts(5,9): error TS2554: Expected 0 arguments, but got 1.
tests/cases/compiler/blockScopedSameNameFunctionDeclarationES6.ts(5,9): error TS2717: No overload expects 1 arguments. The most matching overloads expect 0 arguments.
tests/cases/compiler/blockScopedSameNameFunctionDeclarationES6.ts(8,18): error TS2393: Duplicate function implementation.
tests/cases/compiler/blockScopedSameNameFunctionDeclarationES6.ts(10,9): error TS2554: Expected 0 arguments, but got 1.
tests/cases/compiler/blockScopedSameNameFunctionDeclarationES6.ts(12,5): error TS2554: Expected 0 arguments, but got 1.
tests/cases/compiler/blockScopedSameNameFunctionDeclarationES6.ts(10,9): error TS2717: No overload expects 1 arguments. The most matching overloads expect 0 arguments.
tests/cases/compiler/blockScopedSameNameFunctionDeclarationES6.ts(12,5): error TS2717: No overload expects 1 arguments. The most matching overloads expect 0 arguments.
tests/cases/compiler/blockScopedSameNameFunctionDeclarationES6.ts(16,1): error TS2554: Expected 1 arguments, but got 0.


Expand All @@ -15,7 +15,7 @@ tests/cases/compiler/blockScopedSameNameFunctionDeclarationES6.ts(16,1): error T
foo();
foo(10); // not ok
~~~~~~~
!!! error TS2554: Expected 0 arguments, but got 1.
!!! error TS2717: No overload expects 1 arguments. The most matching overloads expect 0 arguments.
}
else {
function foo() { } // duplicate
Expand All @@ -24,11 +24,11 @@ tests/cases/compiler/blockScopedSameNameFunctionDeclarationES6.ts(16,1): error T
foo();
foo(10);// not ok
~~~~~~~
!!! error TS2554: Expected 0 arguments, but got 1.
!!! error TS2717: No overload expects 1 arguments. The most matching overloads expect 0 arguments.
}
foo(10); // not ok
~~~~~~~
!!! error TS2554: Expected 0 arguments, but got 1.
!!! error TS2717: No overload expects 1 arguments. The most matching overloads expect 0 arguments.
foo();
}
foo(10);
Expand Down
16 changes: 8 additions & 8 deletions tests/baselines/reference/classWithConstructors.errors.txt
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
tests/cases/conformance/classes/members/constructorFunctionTypes/classWithConstructors.ts(6,13): error TS2554: Expected 1 arguments, but got 0.
tests/cases/conformance/classes/members/constructorFunctionTypes/classWithConstructors.ts(15,14): error TS2554: Expected 1 arguments, but got 0.
tests/cases/conformance/classes/members/constructorFunctionTypes/classWithConstructors.ts(21,13): error TS2554: Expected 1 arguments, but got 0.
tests/cases/conformance/classes/members/constructorFunctionTypes/classWithConstructors.ts(15,14): error TS2717: No overload expects 0 arguments. The most matching overloads expect 1 arguments.
tests/cases/conformance/classes/members/constructorFunctionTypes/classWithConstructors.ts(21,13): error TS2717: No overload expects 0 arguments. The most matching overloads expect 1 arguments.
tests/cases/conformance/classes/members/constructorFunctionTypes/classWithConstructors.ts(31,13): error TS2554: Expected 1 arguments, but got 0.
tests/cases/conformance/classes/members/constructorFunctionTypes/classWithConstructors.ts(40,14): error TS2554: Expected 1-2 arguments, but got 0.
tests/cases/conformance/classes/members/constructorFunctionTypes/classWithConstructors.ts(46,13): error TS2554: Expected 1-2 arguments, but got 0.
tests/cases/conformance/classes/members/constructorFunctionTypes/classWithConstructors.ts(40,14): error TS2717: No overload expects 0 arguments. The most matching overloads expect 1 arguments.
tests/cases/conformance/classes/members/constructorFunctionTypes/classWithConstructors.ts(46,13): error TS2717: No overload expects 0 arguments. The most matching overloads expect 1 arguments.


==== tests/cases/conformance/classes/members/constructorFunctionTypes/classWithConstructors.ts (6 errors) ====
Expand All @@ -25,15 +25,15 @@ tests/cases/conformance/classes/members/constructorFunctionTypes/classWithConstr

var c3 = new C2(); // error
~~~~~~~~
!!! error TS2554: Expected 1 arguments, but got 0.
!!! error TS2717: No overload expects 0 arguments. The most matching overloads expect 1 arguments.
var c4 = new C2(''); // ok
var c5 = new C2(1); // ok

class D extends C2 { }

var d = new D(); // error
~~~~~~~
!!! error TS2554: Expected 1 arguments, but got 0.
!!! error TS2717: No overload expects 0 arguments. The most matching overloads expect 1 arguments.
var d2 = new D(1); // ok
var d3 = new D(''); // ok
}
Expand All @@ -56,15 +56,15 @@ tests/cases/conformance/classes/members/constructorFunctionTypes/classWithConstr

var c3 = new C2(); // error
~~~~~~~~
!!! error TS2554: Expected 1-2 arguments, but got 0.
!!! error TS2717: No overload expects 0 arguments. The most matching overloads expect 1 arguments.
var c4 = new C2(''); // ok
var c5 = new C2(1, 2); // ok

class D<T, U> extends C2<T, U> { }

var d = new D(); // error
~~~~~~~
!!! error TS2554: Expected 1-2 arguments, but got 0.
!!! error TS2717: No overload expects 0 arguments. The most matching overloads expect 1 arguments.
var d2 = new D(1); // ok
var d3 = new D(''); // ok
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
tests/cases/conformance/classes/constructorDeclarations/automaticConstructors/derivedClassWithoutExplicitConstructor2.ts(13,9): error TS2554: Expected 1-3 arguments, but got 0.
tests/cases/conformance/classes/constructorDeclarations/automaticConstructors/derivedClassWithoutExplicitConstructor2.ts(30,9): error TS2554: Expected 1-3 arguments, but got 0.
tests/cases/conformance/classes/constructorDeclarations/automaticConstructors/derivedClassWithoutExplicitConstructor2.ts(13,9): error TS2717: No overload expects 0 arguments. The most matching overloads expect 1 arguments.
tests/cases/conformance/classes/constructorDeclarations/automaticConstructors/derivedClassWithoutExplicitConstructor2.ts(30,9): error TS2717: No overload expects 0 arguments. The most matching overloads expect 1 arguments.


==== tests/cases/conformance/classes/constructorDeclarations/automaticConstructors/derivedClassWithoutExplicitConstructor2.ts (2 errors) ====
Expand All @@ -17,7 +17,7 @@ tests/cases/conformance/classes/constructorDeclarations/automaticConstructors/de

var r = new Derived(); // error
~~~~~~~~~~~~~
!!! error TS2554: Expected 1-3 arguments, but got 0.
!!! error TS2717: No overload expects 0 arguments. The most matching overloads expect 1 arguments.
var r2 = new Derived(1);
var r3 = new Derived(1, 2);
var r4 = new Derived(1, 2, 3);
Expand All @@ -36,7 +36,7 @@ tests/cases/conformance/classes/constructorDeclarations/automaticConstructors/de

var d = new D(); // error
~~~~~~~
!!! error TS2554: Expected 1-3 arguments, but got 0.
!!! error TS2717: No overload expects 0 arguments. The most matching overloads expect 1 arguments.
var d2 = new D(new Date()); // ok
var d3 = new D(new Date(), new Date());
var d4 = new D(new Date(), new Date(), new Date());
4 changes: 2 additions & 2 deletions tests/baselines/reference/functionOverloads29.errors.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
tests/cases/compiler/functionOverloads29.ts(4,9): error TS2554: Expected 1 arguments, but got 0.
tests/cases/compiler/functionOverloads29.ts(4,9): error TS2717: No overload expects 0 arguments. The most matching overloads expect 1 arguments.


==== tests/cases/compiler/functionOverloads29.ts (1 errors) ====
Expand All @@ -7,5 +7,5 @@ tests/cases/compiler/functionOverloads29.ts(4,9): error TS2554: Expected 1 argum
function foo(bar:any):any{ return bar }
var x = foo();
~~~~~
!!! error TS2554: Expected 1 arguments, but got 0.
!!! error TS2717: No overload expects 0 arguments. The most matching overloads expect 1 arguments.

4 changes: 2 additions & 2 deletions tests/baselines/reference/functionOverloads34.errors.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
tests/cases/compiler/functionOverloads34.ts(4,9): error TS2554: Expected 1 arguments, but got 0.
tests/cases/compiler/functionOverloads34.ts(4,9): error TS2717: No overload expects 0 arguments. The most matching overloads expect 1 arguments.


==== tests/cases/compiler/functionOverloads34.ts (1 errors) ====
Expand All @@ -7,5 +7,5 @@ tests/cases/compiler/functionOverloads34.ts(4,9): error TS2554: Expected 1 argum
function foo(bar:{a:any;}):any{ return bar }
var x = foo();
~~~~~
!!! error TS2554: Expected 1 arguments, but got 0.
!!! error TS2717: No overload expects 0 arguments. The most matching overloads expect 1 arguments.

4 changes: 2 additions & 2 deletions tests/baselines/reference/functionOverloads37.errors.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
tests/cases/compiler/functionOverloads37.ts(4,9): error TS2554: Expected 1 arguments, but got 0.
tests/cases/compiler/functionOverloads37.ts(4,9): error TS2717: No overload expects 0 arguments. The most matching overloads expect 1 arguments.


==== tests/cases/compiler/functionOverloads37.ts (1 errors) ====
Expand All @@ -7,5 +7,5 @@ tests/cases/compiler/functionOverloads37.ts(4,9): error TS2554: Expected 1 argum
function foo(bar:{a:any;}[]):any{ return bar }
var x = foo();
~~~~~
!!! error TS2554: Expected 1 arguments, but got 0.
!!! error TS2717: No overload expects 0 arguments. The most matching overloads expect 1 arguments.

8 changes: 4 additions & 4 deletions tests/baselines/reference/overload1.errors.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
tests/cases/compiler/overload1.ts(27,5): error TS2322: Type 'C' is not assignable to type 'string'.
tests/cases/compiler/overload1.ts(29,1): error TS2322: Type 'number' is not assignable to type 'string'.
tests/cases/compiler/overload1.ts(31,3): error TS2554: Expected 1-2 arguments, but got 3.
tests/cases/compiler/overload1.ts(32,3): error TS2554: Expected 1-2 arguments, but got 0.
tests/cases/compiler/overload1.ts(31,3): error TS2717: No overload expects 3 arguments. The most matching overloads expect 2 arguments.
tests/cases/compiler/overload1.ts(32,3): error TS2717: No overload expects 0 arguments. The most matching overloads expect 1 arguments.
tests/cases/compiler/overload1.ts(33,1): error TS2322: Type 'C' is not assignable to type 'string'.
tests/cases/compiler/overload1.ts(34,9): error TS2345: Argument of type '2' is not assignable to parameter of type 'string'.

Expand Down Expand Up @@ -43,10 +43,10 @@ tests/cases/compiler/overload1.ts(34,9): error TS2345: Argument of type '2' is n
var z:string=x.g(x.g(3,3)); // good
z=x.g(2,2,2); // no match
~~~~~~~~~~
!!! error TS2554: Expected 1-2 arguments, but got 3.
!!! error TS2717: No overload expects 3 arguments. The most matching overloads expect 2 arguments.
z=x.g(); // no match
~~~~~
!!! error TS2554: Expected 1-2 arguments, but got 0.
!!! error TS2717: No overload expects 0 arguments. The most matching overloads expect 1 arguments.
z=x.g(new O.B()); // ambiguous (up and down conversion)
~
!!! error TS2322: Type 'C' is not assignable to type 'string'.
Expand Down
11 changes: 11 additions & 0 deletions tests/baselines/reference/overload3.errors.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
tests/cases/compiler/overload3.ts(4,1): error TS2717: No overload expects 2 arguments. The most matching overloads expect either 1 or 3 arguments.


==== tests/cases/compiler/overload3.ts (1 errors) ====
declare function foo(x: number): void;
declare function foo(x: number, y: number, z: number): void;

foo(1, 2);
~~~~~~~~~
!!! error TS2717: No overload expects 2 arguments. The most matching overloads expect either 1 or 3 arguments.

9 changes: 9 additions & 0 deletions tests/baselines/reference/overload3.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
//// [overload3.ts]
declare function foo(x: number): void;
declare function foo(x: number, y: number, z: number): void;

foo(1, 2);


//// [overload3.js]
foo(1, 2);
14 changes: 14 additions & 0 deletions tests/baselines/reference/overload3.symbols
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
=== tests/cases/compiler/overload3.ts ===
declare function foo(x: number): void;
>foo : Symbol(foo, Decl(overload3.ts, 0, 0), Decl(overload3.ts, 0, 38))
>x : Symbol(x, Decl(overload3.ts, 0, 21))

declare function foo(x: number, y: number, z: number): void;
>foo : Symbol(foo, Decl(overload3.ts, 0, 0), Decl(overload3.ts, 0, 38))
>x : Symbol(x, Decl(overload3.ts, 1, 21))
>y : Symbol(y, Decl(overload3.ts, 1, 31))
>z : Symbol(z, Decl(overload3.ts, 1, 42))

foo(1, 2);
>foo : Symbol(foo, Decl(overload3.ts, 0, 0), Decl(overload3.ts, 0, 38))

17 changes: 17 additions & 0 deletions tests/baselines/reference/overload3.types
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
=== tests/cases/compiler/overload3.ts ===
declare function foo(x: number): void;
>foo : { (x: number): void; (x: number, y: number, z: number): void; }
>x : number

declare function foo(x: number, y: number, z: number): void;
>foo : { (x: number): void; (x: number, y: number, z: number): void; }
>x : number
>y : number
>z : number

foo(1, 2);
>foo(1, 2) : any
>foo : { (x: number): void; (x: number, y: number, z: number): void; }
>1 : 1
>2 : 2

Loading