When two-dimensional arrays meet destructuring, it results in a type error

Can anyone clarify TypeScript behavior in this scenario?

  • JavaScript

    const test1 = [
        ['a', 'b'],
        ['c', 'd'],
    ];
    
    const test2 = [
        ...[
            ['a', 'b'],
            ['c', 'd'],
        ],
    ];
    
    console.log(JSON.stringify(test1) === JSON.stringify(test2));
    

    The output will be true since the arrays are identical.

  • TypeScript

    const test1: [string, string][] = [
        ['a', 'b'],
        ['c', 'd'],
    ];
    
    const test2: [string, string][] = [
        ...[
            ['a', 'b'],
            ['c', 'd'],
        ],
    ];
    

    However, with TypeScript, an error occurs on test2:

    Type 'string[][]' is not assignable to type '[string, string][]'.
      Type 'string[]' is not assignable to type '[string, string]'.
        Target requires 2 element(s) but source may have fewer.
    

You can view a reproducer on TypeScript Playground.

Is there a way to make this work without resorting to complicated type casting?


UPDATE

Here's a more specific example of what I'm trying to achieve:

const someValues = [1, 2, 3];

const test3: [string, string][] = [
    ...someValues.map(value => ['some string', 'another string']),
];

UPDATE #2

Following Алексей Мартинкевич's advice, I found that this solution works:

const someValues = [1, 2, 3];

const test3: (readonly [string, string])[] = [
    ...someValues.map(i => ['a', 'a'] as const),
];

Is there a simpler and clearer approach for my colleagues and my future self to understand?
(avoiding confusion down the road :D)

Answer №1

In this particular scenario with concrete details, you have the option to specify the return type on the arrow function passed to map:

const someValues = [1, 2, 3];

const test3: [string, string][] = [
    ...someValues.map((value): [string, string] => ['some string', 'another string']),
];

If you feel the type is clear enough, you can also omit it from the variable declaration:

const test4 = [
    ...someValues.map((value): [string, string] => ['some string', 'another string']),
];

Answer №2

This particular form of construction is classified as string[][], which means it cannot be reassigned to [string, string][].

...[
 ['a', 'b'],
 ['c', 'd'],
]

The solution lies in the following code snippet:

const test1: [string, string][] = [
    ['a', 'b'],
    ['c', 'd'],
];

const test2: [string, string][] = [
    ...test1,
];

If you opt to use as const, make sure to maintain read-only status on all elements:

const test2: (readonly [string, string])[] = [
    ...[
        ['a', 'b'],
        ['c', 'd'],
    ] as const
]

By default, Typescript assumes arrays are mutable, hence it defaults to a broader type.

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

Cross-component communication in Angular

I'm currently developing a web-based application using angular version 6. Within my application, there is a component that contains another component as its child. In the parent component, there is a specific function that I would like to invoke when ...

Developing a discriminated union by utilizing the attribute names from a different type

In my quest to create a unique generic type, I am experimenting with extracting property names and types from a given type to create a discriminated union type. Take for example: type FooBar = { foo: string; bar: number; }; This would translate t ...

React Component - Element with an undefined value

When I tried implementing an Ionic Modal as a React Component, I encountered the following error message: Type '({ onClose, tipo }: PropsWithChildren<{ onClose: any; tipo: number; }>) => Element | undefined' is not assignable to type & ...

Obtain the hexadecimal color code based on the MUI palette color name

Is there a way to extract a hexcode or any color code from a palette color name in Material UI? Here is my use case: I have a customized Badge that I want to be able to modify just like the normal badges using the color property. The component code looks ...

How can I assign a type to an array object by utilizing both the 'Pick' and '&' keywords simultaneously in TypeScript?

As a beginner in TypeScript, I am looking to declare a type for an array object similar to the example below. const temp = [{ id: 0, // number follower_id: 0, // number followee_id: 0, // number created_at: '', // string delete_at: &ap ...

The Dilemma of using forRoot() in Angular 2/4+ Shared Modules

After uncovering the treasure that is forRoot() while delving deeper into Angular dependency injection (DI), I find myself pondering on the best practices for its usage. I came across this method when trying to enable a lazy loaded module to access a serv ...

Guide on converting a JSON object into a TypeScript Object

I'm currently having issues converting my JSON Object into a TypeScript class with matching attributes. Can someone help me identify what I'm doing wrong? Employee Class export class Employee{ firstname: string; lastname: string; bi ...

Parent observable method encountering an error while grouping multiple HTTP calls in Angular

I am facing an issue with managing multiple http calls and handling errors that may occur during their execution. I want to be able to identify which calls have failed so that I can retry them using a different method. However, without visibility at the co ...

Using Rollup alongside @rollup/plugin-babel and Typescript: Anticipated a comma, received a colon instead

I've encountered a problem while working with Rollup 4: [!] RollupError: Expected ',', got ':' (Note that you need plugins to import files that are not JavaScript) src/index.ts (48:19) Although my Babel configuration appears to ...

Leveraging WebStorm's TypeScript support in conjunction with node_modules

Attempting to set up a TypeScript project in WebStorm to import a Node.js module has been a struggle. I made sure to download the necessary TypeScript definition in settings and specified --module commonjs in the compiler settings. However, I keep running ...

ESLint refuses to be turned off for a particular file

I am in the process of creating a Notes.ts file specifically for TypeScript notes. I require syntax highlighting but do not want to use eslint. How can I prevent eslint from running on my notes file? Directory Structure root/.eslintignore root/NestJS.ts r ...

Is it necessary to manually validate parameters in TypeScript when developing a library?

Understanding the basic workings of TypeScript, it's clear that TypeScript transpiles code to JavaScript without adding extra behavior like type checking during execution. For instance, function example(parameter: string): void { console.log(paramet ...

Looking to resolve a module-specific error in Angular that has not been identified

While practicing Angular, I encountered an error during compilation: Module not found: Error: Can't resolve './app.component.css' in 'D:\hello-world-app\src\app' i 「wdm」: Failed to compile. This is my app.compo ...

Converting API response into a class instance using `class-transformer` in TypeScript: A step-by-step guide

When working with TypeScript, I have a regular method called Request(method: HttpMethod, url: string, ...) that is used for calling APIs. Now, my goal is to convert the response from this API request into an instance of a class using class-transformer (or ...

Multiple components are returned with switch case

I am trying to iterate over an object and display a result based on Object.entries. However, the loop currently stops at the first return statement. Is there a way for me to capture and display all components returned simultaneously, perhaps using a vari ...

Angular examine phrases barring the inclusion of statuses within parentheses

I require some assistance. Essentially, there is a master list (arrList) and a selected list (selectedArr). I am comparing the 'id' and 'name' from the master list to those in the selected list, and then checking if they match to determ ...

Component fails to navigate to the page of another component

Hello there. I am facing an issue where the button with routelink in the RegistrationComponent is not routing to the page of LogInComponent and I cannot figure out why. Angular is not throwing any errors. Here is the RouteComponent along with its view: im ...

RxJS: when combined with timer, groupBy operator does not emit any values

Just starting out with RxJS version 6.5.5, I'm encountering an issue with the groupBy operator. Here's a simplified example to showcase the problem. I have a function called retrieveFiles() that retrieves an array of strings. function async ret ...

What are the steps to set up ChartJS on a personal computer?

Currently, I am working on creating charts with ChartJS using the CDN version. However, I would like to have it installed directly on my website. After downloading ChartJS v4.1.1, I realized that it only contains typescript files. Since I cannot use TS fil ...

Is there a way to seamlessly share TypeScript types between my Node.js/Express server and Vite-React frontend during deployment?

I'm currently tackling a project that involves a Node.js/Express backend and a Vite-React frontend. My goal is to efficiently share TypeScript types between the two. How should I configure my project and build process to achieve this seamless type sha ...