Unreliable TypeScript errors when using spread arguments

Consider this function:

function foo(a: number, b: number) {/* ... */}

Error is triggered by Snippet 1:

foo(1, ...[]);

Expected 2 arguments, but received only 1.

Error is triggered by Snippet 2:

foo(1, 2, ...[]);

Expected 2 arguments, but received 3 or more.

The discrepancy in error messages between snippets 1 and 2 raises questions about TypeScript behavior. There seems to be a distinction that is not immediately clear.

Why does TypeScript treat these two snippets differently?


To resolve the issue for users facing a similar error, type spreaded arguments more rigorously, such as:

foo(1, ...[2] as const);
foo(1, ...[2] as [number]);
foo(1, 2, ...[] as const);
foo(1, 2, ...[] as []);

Answer №1

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

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Can TypeScript allow the usage of variables as type declarations?

Can someone help me understand how to avoid using this particular pattern (b[firstCriteria] as number)? I need the function to be type-safe and only allow passing an existing key from the object inside the array. I'm encountering an error in TypeScri ...

Potential absence of object.ts(2531)

Currently, I am working on a project using Node.js with Typescript. My task involves finding a specific MongoDB document, updating certain values within it, and then saving the changes made. However, when I try to save the updated document, an error is bei ...

Understanding the Typescript Type for a JSON Schema Object

When working with JSON-schema objects in typescript, is there a specific type that should be associated with them? I currently have a method within my class that validates whether its members adhere to the dynamic json schema schema. This is how I am doing ...

What is the best way to find out if an array index is within a certain distance of another index?

I'm currently developing a circular carousel feature. With an array of n items, where n is greater than 6 in my current scenario, I need to identify all items within the array that are either less than or equal to 3 positions away from a specific inde ...

The interactive Material UI Radio buttons are not responding to click events due to dynamic generation

Click here to see the demo in action: https://codesandbox.io/s/material-demo-9fwlz I expected this code to produce checkable radio elements, but it doesn't seem to be working correctly. Can anyone identify what might be causing the issue? This code s ...

Issue with Nodemon and Typescript causing errors with Worker Threads

Currently, I am in the process of integrating a worker thread into my Typescript and node.js application. Let's take a look at my thread.ts file: import { Worker, isMainThread, parentPort, workerData } from "worker_threads"; let thread ...

The error message "@graphql-eslint/eslint-plugin: problem with the "parserOptions.schema" configuration"

Our team is currently working on developing micro-services using NestJS with Typescript. Each of these services exposes a GraphQL schema, and to combine them into a single graph, we are utilizing a federation service built with NestJS as well. I recently ...

Issues with the messaging functionality of socket.io

Utilizing socket.io and socket.io-client, I have set up a chat system for users and operators. The connections are established successfully, but I am encountering strange behavior when it comes to sending messages. For instance, when I send a message from ...

TypeScript excels in typechecking when using two individual assignments, but may encounter issues when attempting typechecking with tuple

I am quite puzzled by a discovery I made and I am seeking to understand why TypeScript is displaying this behavior and what the underlying reason may be. Here is the code snippet: class A { constructor(public name : String, public x = 0, public y = 0) ...

JavaScript: Manipulating Data with Dual Arrays of Objects

//Original Data export const data1 = [ { addKey: '11', address: '12', value: 0 }, { addKey: '11', address: '12', value: 0 }, { addKey: '12', address: '11', value: 0 }, { addKey: &a ...

Sending a style prop to a React component

My typescript Next.js app seems to be misbehaving, or perhaps I'm just not understanding something properly. I have a component called <CluckHUD props="styles.Moon" /> that is meant to pass the theme as a CSS classname in order to c ...

Trouble with V-if not updating after property is modified within an async TypeScript function

There is a scenario where one HTML element becomes hidden after an async call returns from the server, while another HTML element is displayed: <template> <div v-if="!showElementTwo">Element 1</div> <div v-if="show ...

Updating a component in Angular 4.3.1 from within an observable callback

My Project Journey I am currently immersing myself in learning Angular by working on a personal project: developing a game that involves routing, services, and more. One of the requirements is to hide the header on the landing page (route for '/&apos ...

Can you provide the syntax for a generic type parameter placed in front of a function type declaration?

While reviewing a project code recently, I came across some declarations in TypeScript that were unfamiliar to me: export interface SomeInterface<T> { <R>(paths: string[]): Observable<R>; <R>(Fn: (state: T) => R): Observable ...

Assistance needed with C programming: How can I store strings from a text file into a character array? The text file is being accessed via a command line argument, just so you know

In my current project, I am working on developing a program that is designed to read in a .txt file through command line arguments and then encrypt the message contained within that file. After successfully using pointers to open the text file, I have enc ...

What is the best way to troubleshoot substrings for accurately reading URLs from an object?

While a user inputs a URL, I am attempting to iterate through an object to avoid throwing an error message until a substring does not match the beginning of any of the URLs in my defined object. Object: export const urlStrings: { [key: string]: string } = ...

Attempting to utilize the setInterval function in Ionic 4 to invoke a specific function every second, unfortunately, the function fails to execute

Working with Ionic 4 has been a breeze for me. Recently, I encountered a situation where I needed to update the value of an ion-range every second by invoking a function. However, despite successfully compiling the code, the changeMark function never seeme ...

Exploring the potential of utilizing arguments within the RxJS/map operator

When working with rxjs, export function map<T, R, A>(project: (this: A, value: T, index: number) => R, thisArg: A): OperatorFunction<T, R>; I seem to be struggling to find a practical use for thisArg: A. ...

"Upon submitting a form in React JS, the components will automatically trigger a

Within my application, there is a Mobx storage in conjunction with a modal window component. The form within the modal window allows me to collect all the properties and push them into an array named 'cart' within the storage as an object. Take a ...

Exploring subclasses in TypeScript

When working with TypeScript and defining an interface like the one below: export interface IMyInterface { category: "Primary" | "Secondary" | "Tertiary", } Can we access the specific "sub types" of the category, such as ...