Here is an example of a simple scenario without any confusing elements:
declare const arr: number[];
function foo(a: number, b: number) {/* ... */ }
foo(...arr); // expected 2, got 0 or more
foo(1, ...arr); // expected 2, got 1 or more
foo(1, 2, ...arr) // expected 2, got *3* or more ?!
foo(1, 2, 3, ...arr) // expected 2, got *4* or more ?!
These are all errors because in the first two cases, the function must error out if not enough arguments are passed.
In the last two cases, one might argue that there should be no error since it's generally safe to provide extra parameters to a function. However, the compiler still raises an error here.
The reasoning behind the specific wording of the error message "3 or more" instead of "2 or more" is explained in a pull request on GitHub by Microsoft regarding excess spread arguments:
This PR also changes 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 arguments, but got at least 3", which is technically correct but not very clear.
The decision was made to ensure clarity and avoid confusion among users when interpreting the error messages.
You can find further details in the original pull request.
Although some may disagree with this approach, discussions have taken place on GitHub issues such as microsoft/TypeScript#20097 and microsoft/TypeScript#20372. Feel free to contribute to these discussions or suggest improvements.
Hope this clarifies things for you. Good luck!
Playground link for reference