From 8657dc10a74086d93058a59e072f2e7edcec5b2f Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Thu, 16 Nov 2017 09:31:50 -0800 Subject: [PATCH] Error on excess spread arguments Make the *technically* correct construction illegal: ```ts declare function f(n: number): void; declare var ns: number[]; f(1, ...ns); ``` This call only makes sense if `ns = []`, but in that case, why pass `ns` at all? Allowing this call masks other errors when functions are refactored to have fewer parameters, or to stop using rest parameters: ```ts declare function old(...ns: number[]): void; declare function new(ns: number | number[]): void; old(1, ...ns); // Fine! new(1, ...ns); // Should error! ``` This change the error for excess spread arguments to be more understandable: "Expected 3 arguments, but got least 4". Previously the error would have been "Expected 3 argument, but got at least 3", which is, again, technically correct, but not understandable. --- src/compiler/checker.ts | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 022aa18a50e..e7f954f7295 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -15790,10 +15790,10 @@ namespace ts { return false; } - // If spread arguments are present, check that they correspond to a rest parameter. If so, no - // further checking is necessary. + // If a spread argument is present, check that it corresponds to a rest parameter or at least that it's in the valid range. if (spreadArgIndex >= 0) { - return isRestParameterIndex(signature, spreadArgIndex) || spreadArgIndex >= signature.minArgumentCount; + return isRestParameterIndex(signature, spreadArgIndex) || + signature.minArgumentCount <= spreadArgIndex && spreadArgIndex < signature.parameters.length; } // Too many arguments implies incorrect arity. @@ -16501,7 +16501,10 @@ namespace ts { const paramCount = hasRestParameter ? min : min < max ? min + "-" + max : min; - const argCount = args.length - (hasSpreadArgument ? 1 : 0); + let argCount = args.length; + if (argCount <= max && hasSpreadArgument) { + argCount--; + } 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 :