diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index bd6c5d02cbe63..73c7fb567ac85 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -19789,14 +19789,31 @@ namespace ts { } function getTypeArgumentArityError(node: Node, signatures: ReadonlyArray, typeArguments: NodeArray) { - let min = Infinity; - let max = -Infinity; + const argCount = typeArguments.length; + // No overloads exist + if (signatures.length === 1) { + const sig = signatures[0]; + const min = getMinTypeArgumentCount(sig.typeParameters); + const max = length(sig.typeParameters); + return createDiagnosticForNodeArray(getSourceFileOfNode(node), typeArguments, Diagnostics.Expected_0_type_arguments_but_got_1, min < max ? min + "-" + max : min , argCount); + } + // Overloads exist + let belowArgCount = -Infinity; + let aboveArgCount = Infinity; for (const sig of signatures) { - min = Math.min(min, getMinTypeArgumentCount(sig.typeParameters)); - max = Math.max(max, length(sig.typeParameters)); + const min = getMinTypeArgumentCount(sig.typeParameters); + const max = length(sig.typeParameters); + if (min > argCount) { + aboveArgCount = Math.min(aboveArgCount, min); + } + else if (max < argCount) { + belowArgCount = Math.max(belowArgCount, max); + } + } + if (belowArgCount !== -Infinity && aboveArgCount !== Infinity) { + return createDiagnosticForNodeArray(getSourceFileOfNode(node), typeArguments, Diagnostics.No_overload_expects_0_type_arguments_but_overloads_do_exist_that_expect_either_1_or_2_type_arguments, argCount, belowArgCount, aboveArgCount); } - const paramCount = min === max ? min : min + "-" + max; - return createDiagnosticForNodeArray(getSourceFileOfNode(node), typeArguments, Diagnostics.Expected_0_type_arguments_but_got_1, paramCount, typeArguments.length); + return createDiagnosticForNodeArray(getSourceFileOfNode(node), typeArguments, Diagnostics.Expected_0_type_arguments_but_got_1, belowArgCount === -Infinity ? aboveArgCount : belowArgCount, argCount); } function resolveCall(node: CallLikeExpression, signatures: ReadonlyArray, candidatesOutArray: Signature[] | undefined, isForSignatureHelp: boolean, fallbackError?: DiagnosticMessage): Signature { diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 1845f2b601d84..f669c0721569b 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -2529,6 +2529,10 @@ "category": "Error", "code": 2742 }, + "No overload expects {0} type arguments, but overloads do exist that expect either {1} or {2} type arguments.": { + "category": "Error", + "code": 2743 + }, "Import declaration '{0}' is using private name '{1}'.": { "category": "Error", diff --git a/tests/baselines/reference/functionTypeArgumentArityErrors.errors.txt b/tests/baselines/reference/functionTypeArgumentArityErrors.errors.txt new file mode 100644 index 0000000000000..22e22785a2487 --- /dev/null +++ b/tests/baselines/reference/functionTypeArgumentArityErrors.errors.txt @@ -0,0 +1,57 @@ +tests/cases/compiler/functionTypeArgumentArityErrors.ts(4,4): error TS2743: No overload expects 2 type arguments, but overloads do exist that expect either 1 or 3 type arguments. +tests/cases/compiler/functionTypeArgumentArityErrors.ts(5,4): error TS2558: Expected 4 type arguments, but got 5. +tests/cases/compiler/functionTypeArgumentArityErrors.ts(10,4): error TS2743: No overload expects 2 type arguments, but overloads do exist that expect either 1 or 3 type arguments. +tests/cases/compiler/functionTypeArgumentArityErrors.ts(11,4): error TS2558: Expected 3 type arguments, but got 4. +tests/cases/compiler/functionTypeArgumentArityErrors.ts(16,4): error TS2558: Expected 0 type arguments, but got 1. +tests/cases/compiler/functionTypeArgumentArityErrors.ts(20,4): error TS2558: Expected 2-3 type arguments, but got 1. +tests/cases/compiler/functionTypeArgumentArityErrors.ts(21,4): error TS2558: Expected 2-3 type arguments, but got 4. +tests/cases/compiler/functionTypeArgumentArityErrors.ts(25,4): error TS2558: Expected 2 type arguments, but got 1. +tests/cases/compiler/functionTypeArgumentArityErrors.ts(26,4): error TS2558: Expected 2 type arguments, but got 3. + + +==== tests/cases/compiler/functionTypeArgumentArityErrors.ts (9 errors) ==== + // Overloaded functions with default type arguments + declare function f1(): void; + declare function f1(): void; + f1(); + ~~~~~~~~~~~~~~ +!!! error TS2743: No overload expects 2 type arguments, but overloads do exist that expect either 1 or 3 type arguments. + f1(); + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2558: Expected 4 type arguments, but got 5. + + // Overloaded functions with no default type arguments + declare function f2(): void; + declare function f2(): void; + f2(); + ~~~~~~~~~~~~~~ +!!! error TS2743: No overload expects 2 type arguments, but overloads do exist that expect either 1 or 3 type arguments. + f2(); + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2558: Expected 3 type arguments, but got 4. + + // Overloaded non-generic functions + declare function f3(): void; + declare function f3(a): void; + f3(); + ~~~~~~ +!!! error TS2558: Expected 0 type arguments, but got 1. + + // Generic function with default type parameters + declare function f4(): void; + f4(); + ~~~~~~ +!!! error TS2558: Expected 2-3 type arguments, but got 1. + f4(); + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2558: Expected 2-3 type arguments, but got 4. + + // Generic function with no default type arguments + declare function f5(): void; + f5(); + ~~~~~~ +!!! error TS2558: Expected 2 type arguments, but got 1. + f5(); + ~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2558: Expected 2 type arguments, but got 3. + \ No newline at end of file diff --git a/tests/baselines/reference/functionTypeArgumentArityErrors.js b/tests/baselines/reference/functionTypeArgumentArityErrors.js new file mode 100644 index 0000000000000..9c150bea78be0 --- /dev/null +++ b/tests/baselines/reference/functionTypeArgumentArityErrors.js @@ -0,0 +1,39 @@ +//// [functionTypeArgumentArityErrors.ts] +// Overloaded functions with default type arguments +declare function f1(): void; +declare function f1(): void; +f1(); +f1(); + +// Overloaded functions with no default type arguments +declare function f2(): void; +declare function f2(): void; +f2(); +f2(); + +// Overloaded non-generic functions +declare function f3(): void; +declare function f3(a): void; +f3(); + +// Generic function with default type parameters +declare function f4(): void; +f4(); +f4(); + +// Generic function with no default type arguments +declare function f5(): void; +f5(); +f5(); + + +//// [functionTypeArgumentArityErrors.js] +f1(); +f1(); +f2(); +f2(); +f3(); +f4(); +f4(); +f5(); +f5(); diff --git a/tests/baselines/reference/functionTypeArgumentArityErrors.symbols b/tests/baselines/reference/functionTypeArgumentArityErrors.symbols new file mode 100644 index 0000000000000..48c702f968b46 --- /dev/null +++ b/tests/baselines/reference/functionTypeArgumentArityErrors.symbols @@ -0,0 +1,72 @@ +=== tests/cases/compiler/functionTypeArgumentArityErrors.ts === +// Overloaded functions with default type arguments +declare function f1(): void; +>f1 : Symbol(f1, Decl(functionTypeArgumentArityErrors.ts, 0, 0), Decl(functionTypeArgumentArityErrors.ts, 1, 37)) +>A : Symbol(A, Decl(functionTypeArgumentArityErrors.ts, 1, 20)) + +declare function f1(): void; +>f1 : Symbol(f1, Decl(functionTypeArgumentArityErrors.ts, 0, 0), Decl(functionTypeArgumentArityErrors.ts, 1, 37)) +>A : Symbol(A, Decl(functionTypeArgumentArityErrors.ts, 2, 20)) +>B : Symbol(B, Decl(functionTypeArgumentArityErrors.ts, 2, 22)) +>C : Symbol(C, Decl(functionTypeArgumentArityErrors.ts, 2, 25)) +>D : Symbol(D, Decl(functionTypeArgumentArityErrors.ts, 2, 28)) + +f1(); +>f1 : Symbol(f1, Decl(functionTypeArgumentArityErrors.ts, 0, 0), Decl(functionTypeArgumentArityErrors.ts, 1, 37)) + +f1(); +>f1 : Symbol(f1, Decl(functionTypeArgumentArityErrors.ts, 0, 0), Decl(functionTypeArgumentArityErrors.ts, 1, 37)) + +// Overloaded functions with no default type arguments +declare function f2(): void; +>f2 : Symbol(f2, Decl(functionTypeArgumentArityErrors.ts, 4, 45), Decl(functionTypeArgumentArityErrors.ts, 7, 31)) +>A : Symbol(A, Decl(functionTypeArgumentArityErrors.ts, 7, 20)) + +declare function f2(): void; +>f2 : Symbol(f2, Decl(functionTypeArgumentArityErrors.ts, 4, 45), Decl(functionTypeArgumentArityErrors.ts, 7, 31)) +>A : Symbol(A, Decl(functionTypeArgumentArityErrors.ts, 8, 20)) +>B : Symbol(B, Decl(functionTypeArgumentArityErrors.ts, 8, 22)) +>C : Symbol(C, Decl(functionTypeArgumentArityErrors.ts, 8, 25)) + +f2(); +>f2 : Symbol(f2, Decl(functionTypeArgumentArityErrors.ts, 4, 45), Decl(functionTypeArgumentArityErrors.ts, 7, 31)) + +f2(); +>f2 : Symbol(f2, Decl(functionTypeArgumentArityErrors.ts, 4, 45), Decl(functionTypeArgumentArityErrors.ts, 7, 31)) + +// Overloaded non-generic functions +declare function f3(): void; +>f3 : Symbol(f3, Decl(functionTypeArgumentArityErrors.ts, 10, 37), Decl(functionTypeArgumentArityErrors.ts, 13, 28)) + +declare function f3(a): void; +>f3 : Symbol(f3, Decl(functionTypeArgumentArityErrors.ts, 10, 37), Decl(functionTypeArgumentArityErrors.ts, 13, 28)) +>a : Symbol(a, Decl(functionTypeArgumentArityErrors.ts, 14, 20)) + +f3(); +>f3 : Symbol(f3, Decl(functionTypeArgumentArityErrors.ts, 10, 37), Decl(functionTypeArgumentArityErrors.ts, 13, 28)) + +// Generic function with default type parameters +declare function f4(): void; +>f4 : Symbol(f4, Decl(functionTypeArgumentArityErrors.ts, 15, 13)) +>A : Symbol(A, Decl(functionTypeArgumentArityErrors.ts, 18, 20)) +>B : Symbol(B, Decl(functionTypeArgumentArityErrors.ts, 18, 22)) +>C : Symbol(C, Decl(functionTypeArgumentArityErrors.ts, 18, 25)) + +f4(); +>f4 : Symbol(f4, Decl(functionTypeArgumentArityErrors.ts, 15, 13)) + +f4(); +>f4 : Symbol(f4, Decl(functionTypeArgumentArityErrors.ts, 15, 13)) + +// Generic function with no default type arguments +declare function f5(): void; +>f5 : Symbol(f5, Decl(functionTypeArgumentArityErrors.ts, 20, 37)) +>A : Symbol(A, Decl(functionTypeArgumentArityErrors.ts, 23, 20)) +>B : Symbol(B, Decl(functionTypeArgumentArityErrors.ts, 23, 22)) + +f5(); +>f5 : Symbol(f5, Decl(functionTypeArgumentArityErrors.ts, 20, 37)) + +f5(); +>f5 : Symbol(f5, Decl(functionTypeArgumentArityErrors.ts, 20, 37)) + diff --git a/tests/baselines/reference/functionTypeArgumentArityErrors.types b/tests/baselines/reference/functionTypeArgumentArityErrors.types new file mode 100644 index 0000000000000..c91cf39674fe8 --- /dev/null +++ b/tests/baselines/reference/functionTypeArgumentArityErrors.types @@ -0,0 +1,67 @@ +=== tests/cases/compiler/functionTypeArgumentArityErrors.ts === +// Overloaded functions with default type arguments +declare function f1(): void; +>f1 : { (): void; (): void; } + +declare function f1(): void; +>f1 : { (): void; (): void; } + +f1(); +>f1() : any +>f1 : { (): void; (): void; } + +f1(); +>f1() : any +>f1 : { (): void; (): void; } + +// Overloaded functions with no default type arguments +declare function f2(): void; +>f2 : { (): void; (): void; } + +declare function f2(): void; +>f2 : { (): void; (): void; } + +f2(); +>f2() : any +>f2 : { (): void; (): void; } + +f2(); +>f2() : any +>f2 : { (): void; (): void; } + +// Overloaded non-generic functions +declare function f3(): void; +>f3 : { (): void; (a: any): void; } + +declare function f3(a): void; +>f3 : { (): void; (a: any): void; } +>a : any + +f3(); +>f3() : any +>f3 : { (): void; (a: any): void; } + +// Generic function with default type parameters +declare function f4(): void; +>f4 : () => void + +f4(); +>f4() : any +>f4 : () => void + +f4(); +>f4() : any +>f4 : () => void + +// Generic function with no default type arguments +declare function f5(): void; +>f5 : () => void + +f5(); +>f5() : any +>f5 : () => void + +f5(); +>f5() : any +>f5 : () => void + diff --git a/tests/baselines/reference/newMap.errors.txt b/tests/baselines/reference/newMap.errors.txt index 46668890b0714..d8a4f1c522214 100644 --- a/tests/baselines/reference/newMap.errors.txt +++ b/tests/baselines/reference/newMap.errors.txt @@ -1,8 +1,8 @@ -tests/cases/compiler/newMap.ts(1,9): error TS2558: Expected 0-2 type arguments, but got 1. +tests/cases/compiler/newMap.ts(1,9): error TS2743: No overload expects 1 type arguments, but overloads do exist that expect either 0 or 2 type arguments. ==== tests/cases/compiler/newMap.ts (1 errors) ==== new Map(); ~~~~~~ -!!! error TS2558: Expected 0-2 type arguments, but got 1. +!!! error TS2743: No overload expects 1 type arguments, but overloads do exist that expect either 0 or 2 type arguments. \ No newline at end of file diff --git a/tests/baselines/reference/overloadResolution.errors.txt b/tests/baselines/reference/overloadResolution.errors.txt index 6710f697b3cd4..27d0392ca8dbc 100644 --- a/tests/baselines/reference/overloadResolution.errors.txt +++ b/tests/baselines/reference/overloadResolution.errors.txt @@ -1,6 +1,6 @@ tests/cases/conformance/expressions/functionCalls/overloadResolution.ts(27,5): error TS2345: Argument of type '{}' is not assignable to parameter of type 'number'. tests/cases/conformance/expressions/functionCalls/overloadResolution.ts(41,11): error TS2345: Argument of type '""' is not assignable to parameter of type 'number'. -tests/cases/conformance/expressions/functionCalls/overloadResolution.ts(63,5): error TS2558: Expected 1-3 type arguments, but got 4. +tests/cases/conformance/expressions/functionCalls/overloadResolution.ts(63,5): error TS2558: Expected 3 type arguments, but got 4. tests/cases/conformance/expressions/functionCalls/overloadResolution.ts(70,21): error TS2345: Argument of type '3' is not assignable to parameter of type 'string'. tests/cases/conformance/expressions/functionCalls/overloadResolution.ts(71,21): error TS2345: Argument of type '""' is not assignable to parameter of type 'number'. tests/cases/conformance/expressions/functionCalls/overloadResolution.ts(81,5): error TS2344: Type 'boolean' does not satisfy the constraint 'number'. @@ -79,7 +79,7 @@ tests/cases/conformance/expressions/functionCalls/overloadResolution.ts(91,22): // Generic overloads with differing arity called with type argument count that doesn't match any overload fn3(); // Error ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2558: Expected 1-3 type arguments, but got 4. +!!! error TS2558: Expected 3 type arguments, but got 4. // Generic overloads with constraints called with type arguments that satisfy the constraints function fn4(n: T, m: U); diff --git a/tests/baselines/reference/overloadResolutionConstructors.errors.txt b/tests/baselines/reference/overloadResolutionConstructors.errors.txt index fe1c955651bce..2e09a84d13818 100644 --- a/tests/baselines/reference/overloadResolutionConstructors.errors.txt +++ b/tests/baselines/reference/overloadResolutionConstructors.errors.txt @@ -1,6 +1,6 @@ tests/cases/conformance/expressions/functionCalls/overloadResolutionConstructors.ts(27,9): error TS2345: Argument of type '{}' is not assignable to parameter of type 'number'. tests/cases/conformance/expressions/functionCalls/overloadResolutionConstructors.ts(43,15): error TS2345: Argument of type '""' is not assignable to parameter of type 'number'. -tests/cases/conformance/expressions/functionCalls/overloadResolutionConstructors.ts(67,9): error TS2558: Expected 1-3 type arguments, but got 4. +tests/cases/conformance/expressions/functionCalls/overloadResolutionConstructors.ts(67,9): error TS2558: Expected 3 type arguments, but got 4. tests/cases/conformance/expressions/functionCalls/overloadResolutionConstructors.ts(77,25): error TS2345: Argument of type '3' is not assignable to parameter of type 'string'. tests/cases/conformance/expressions/functionCalls/overloadResolutionConstructors.ts(78,25): error TS2345: Argument of type '""' is not assignable to parameter of type 'number'. tests/cases/conformance/expressions/functionCalls/overloadResolutionConstructors.ts(88,9): error TS2344: Type 'boolean' does not satisfy the constraint 'number'. @@ -83,7 +83,7 @@ tests/cases/conformance/expressions/functionCalls/overloadResolutionConstructors // Generic overloads with differing arity called with type argument count that doesn't match any overload new fn3(); // Error ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2558: Expected 1-3 type arguments, but got 4. +!!! error TS2558: Expected 3 type arguments, but got 4. // Generic overloads with constraints called with type arguments that satisfy the constraints interface fn4 { diff --git a/tests/baselines/reference/overloadsAndTypeArgumentArityErrors.errors.txt b/tests/baselines/reference/overloadsAndTypeArgumentArityErrors.errors.txt index 1993a6d7f2c7b..6b64cd8a77311 100644 --- a/tests/baselines/reference/overloadsAndTypeArgumentArityErrors.errors.txt +++ b/tests/baselines/reference/overloadsAndTypeArgumentArityErrors.errors.txt @@ -1,5 +1,5 @@ -tests/cases/compiler/overloadsAndTypeArgumentArityErrors.ts(5,11): error TS2558: Expected 0-2 type arguments, but got 3. -tests/cases/compiler/overloadsAndTypeArgumentArityErrors.ts(6,15): error TS2558: Expected 0-2 type arguments, but got 3. +tests/cases/compiler/overloadsAndTypeArgumentArityErrors.ts(5,11): error TS2558: Expected 2 type arguments, but got 3. +tests/cases/compiler/overloadsAndTypeArgumentArityErrors.ts(6,15): error TS2558: Expected 2 type arguments, but got 3. tests/cases/compiler/overloadsAndTypeArgumentArityErrors.ts(9,1): error TS2554: Expected 1 arguments, but got 0. @@ -10,10 +10,10 @@ tests/cases/compiler/overloadsAndTypeArgumentArityErrors.ts(9,1): error TS2554: Callbacks('s'); // wrong number of type arguments ~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2558: Expected 0-2 type arguments, but got 3. +!!! error TS2558: Expected 2 type arguments, but got 3. new Callbacks('s'); // wrong number of type arguments ~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2558: Expected 0-2 type arguments, but got 3. +!!! error TS2558: Expected 2 type arguments, but got 3. declare function f(arg: number): void; f(); // wrong number of arguments (#25683) diff --git a/tests/cases/compiler/functionTypeArgumentArityErrors.ts b/tests/cases/compiler/functionTypeArgumentArityErrors.ts new file mode 100644 index 0000000000000..5cf681effa61d --- /dev/null +++ b/tests/cases/compiler/functionTypeArgumentArityErrors.ts @@ -0,0 +1,26 @@ +// Overloaded functions with default type arguments +declare function f1(): void; +declare function f1(): void; +f1(); +f1(); + +// Overloaded functions with no default type arguments +declare function f2(): void; +declare function f2(): void; +f2(); +f2(); + +// Overloaded non-generic functions +declare function f3(): void; +declare function f3(a): void; +f3(); + +// Generic function with default type parameters +declare function f4(): void; +f4(); +f4(); + +// Generic function with no default type arguments +declare function f5(): void; +f5(); +f5();