TypeScript
TypeScript copied to clipboard
Inconsistency with Rest Parameter in Function Type
🔎 Search Terms
rest parameters, parameter list, function parameters
🕗 Version & Regression Information
- This is the behavior in every version I tried, and I reviewed the FAQ for entries about parameters and rest parameters
⏯ Playground Link
https://www.typescriptlang.org/play/?ts=5.4.5&ssl=5&ssc=12&pln=1&pc=1#code/C4TwDgpgBAysBOBLAdgcwGIFdkGNiIHtkoBeKACgDpqBDeVAZwC4oGEVUBtAXQEpSAfFABuBRABMA3AChpOImygQAHjQC2YADYQAjCzhI0WXPiKkKdVHtbs0-EkPnIGBbZU0FU5SzvcQ0wAAWvDLSKupauuQhQA
💻 Code
type StringFunction = (...args: string[]) => void;
const example1: StringFunction = (arg1: string) => console.log(arg1.length);
example1();
🙁 Actual behavior
This code does not display any type errors on any of the versions I tried, but will break at run time on the example1() call.
🙂 Expected behavior
Typescript should prevent the assignment of (arg1: string) => void to a variable of type (...args: string[]) => void since it is possible to have args be empty.
Additional information about the issue
I attempted to search for other issues related to this and came up empty handed. This is different from the "I'm allowed to use a shorter parameter list where a longer one is expected" issue which has drowned out a lot of my searching.
Thanks in advance for any help with this.
I found this in the existing tests: https://github.com/microsoft/TypeScript/blob/79a851426c514a12a75b342e8dd2460ee6615f73/tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithCallSignaturesWithRestParameters.ts#L16
This is a pretty old test though and it assumes strictNullChecks: false. I think it doesn't quite make sense in the strict world for this to be allowed. Rest params are effectively optional so why do we observe a difference here?
// error
const fn1: (a?: string) => void = (a: string) => {}
// ok?
const fn2: (...args: number[]) => void = (x: number) => {};
We can find some recent tests with strict: true that would break if the above wouldn't work:
https://github.com/microsoft/TypeScript/blob/79a851426c514a12a75b342e8dd2460ee6615f73/tests/cases/compiler/assignmentToAnyArrayRestParameters.ts#L6-L14
At the very least f2 and f4 should error here - assuming that the issue at hand would get fixed.
rest param corresponds to infinite number of params
Yeah, no. It can be up to an infinite number of params, but a minimum of zero. i.e. the same reason fn1 is an error in your example.
I guess the reasoning here is the same as how an object with a string index signature is treated in some contexts as having all possible properties at once, which is only rectified by enabling noUncheckedIndexedAccess.
This is an intentional affordance for functions like Regex#replace or (throwback) AMD's define call.
In practice any time you alias a function into a position with rest args, the number of arguments you'll get is almost always determinable at the call site (e.g. by the number of groups in the regex, the number of module names passed to define, and so on)
I could swear we discussed this on GitHub (not CodePlex) but I can't find it - very hard to search for
This issue has been marked as "Working as Intended" and has seen no recent activity. It has been automatically closed for house-keeping purposes.