Adding new types to a tuple type in TypeScript

My goal is to add types to the elements of a tuple using spread syntax. Here is an example:

type A = [a:number,b:string] 
type B = [...A,c:boolean]

The desired result should be

type B = [a:number,b:string,c:boolean]

However, when I attempted this approach, I encountered the following error message:

Tuple members must all have names or all not have names.ts(5084)

https://i.sstatic.net/PvjVg.png

I am curious about the root cause of this issue. If anyone has any insights or suggestions, please feel free to share.

Answer №1

Refer to microsoft/TypeScript#43516 for the definitive answer to this query.

Your usage involves labeled tuple elements; the a, b, and c in your tuples act as labels for documentation purposes but do not impact assignability.

As per the TypeScript release notes, a key rule with labeled tuple elements is that either all elements of a tuple must be labeled, or none can bear labels. In the context of:

type B = [...A, c: boolean];

The initial spread of type A within a variadic tuple is unlabeled, while the last element of type boolean carries a label, rendering the type illegal.

According to microsoft/TypeScript#43516, you must provide a name for that initial rest element:

type B = [...args: A, c: boolean]; 
// --------> ^^^^^^ <----- assign a label here
// type B = [a: number, b: string, c: boolean]

Although slightly awkward because the labels from A supersede the args label from

B</code, it becomes necessary to supply something that will essentially be disregarded immediately.</p>
<p>However, according to <a href="https://github.com/microsoft/TypeScript/issues/39941" rel="nofollow noreferrer">microsoft/TypeScript#39941</a> (refer to <a href="https://github.com/microsoft/TypeScript/issues/39941#issuecomment-778868736" rel="nofollow noreferrer">this comment</a>) and discussions in <a href="https://github.com/microsoft/TypeScript/issues/43744" rel="nofollow noreferrer">microsoft/TypeScript#43744</a>, this rule exists because there are scenarios where the label is essential, and distinguishing them syntactically is apparently challenging.</p>
<p>For instance, if <code>A
were a standard array type, then you would have an output like a tuple with a leading rest element, with the provided label pertaining to that rest element:

type AA = number[];
type BB = [...args: AA, c: boolean];
// type BB = [...args: number[], c: boolean]

There are suggestions in the linked issues about potentially relaxing the rule to accommodate cases similar to yours. However, this has not been integrated into the language thus far.

So there you have it. If you wish to add a label to one element in a tuple, consistency mandates assigning labels to all elements, including those spread from other tuple types.

Click here for a code demo on TypeScript playground

Answer №2

It seems like the correct way to write it is

const TypeA = [num: 1, let: 'abc']
const TypeB = [...required_dummy_value: TypeA, bool: true]

The reasoning behind this structure is not clear to me. When I attempted to fix it, the editor recommended the following:

const NewType = [dummy: ...TypeA, bool: true] // warning: make sure label comes before ellipsis

Answer №3

Define a new array type by combining existing tuple types within it.

To achieve this, follow these simple steps:

type X = [first: number, second: string] 
type Y = [third: boolean]

type Z = [...X, ...Y]

Explore the Typescript Playground here

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

The type 'undefined' cannot be assigned to the type 'string | Buffer | { key: string | Buffer; passphrase: string; } | GetPublicKeyOrSecret'

Verification Code for JWT This function is used to verify a jwt using typescript. public verify( token: string, secretOrPublicKey?: string | Buffer, options?: jwt.VerifyOptions ): Promise<object | string> { if (!secretOrPublicKey) { ...

Turn TypeScript - Modify type properties to reflect types of their descendants

I am currently working on creating a type that will modify a generic type based on its children. To provide some clarity, I have created a simplified example below: Original type type FormFields = { username: { type: string, ...

Guide on transforming a Unix timestamp into either "2000-01-01" or "2000-05-24 20:00:00" format, or the opposite way, using Deno

Just starting out with Deno and looking to convert a Unix timestamp such as 1646245390158 into either the format of 2000-01-01 or 2000-05-24 20:00:00, or vice versa. Any tips on how to achieve this? ...

The specified property is not present in the type '{}'

I've been incorporating Typescript into my React application Within my mapStateToProps, this is the code I'm using const mapStateToProps = (state: AppState) => { console.log(state) return { ...state.player, position: ...

Why aren't enums that can be derived supported?

Is there a way to create an enum that is a subset of another enum? Sometimes it would be useful to have an enum that is a subset of another Enum with the same values at run time but under a different name. Are there better ways to handle this scenario? ...

What are the best scenarios for implementing abstraction in Angular?

Throughout my experience, I have encountered Java EE, .Net, and various other enterprise application architectures. In each case, there was always an abstract upper class - like AbstractService for generalizing the service layer. However, in Angular, I ha ...

Changing background color during drag and drop in Angular 2: A step-by-step guide

A drag and drop container has been created using Angular 2 typescript. The goal is to alter the background color of the drag & drop container while dragging a file into it. Typescript: @HostListener('dragover', ['$event']) public onDr ...

Error encountered with ts-loader in the node_modules/@types directory within Webpack

After successfully compiling my project, I encountered errors when trying to run npm install and then webpack in a new directory. The errors are as follows: ERROR in /home/nobody/myproject/server/node_modules/@types/mongodb/index.d.ts (500,12): error TS10 ...

Understanding the Purpose of the Pipe Function in Angular 2 and Typescript Observables

Recently, I encountered a situation where I needed to accept an Observer parameter in a function written in Typescript. I struggled to find a solution, reminding me of working with a delegate parameter in C#. The specific scenario involved adding a bookend ...

What is the best method for quickly filtering an array of objects according to the user's input?

What seemed like a simple task has me puzzled. I'm trying to sort through an array of objects based on user input. [{ name: Stan, age: 20, height: 190 }, { name: Pan, age: 30, height: 180 }, { name: Dan, age: 28, height: 185 }, { name: San, age: 20, ...

Unable to display object property on screen after printing Angular 2 array on console

I have written a method in my service: getPost(nid: string): Observable<Post[]>{ let url = "http://test.co.uk/api/v1/basic/" + nid; return this.http.get(url, {headers: this.headers}).map(res => res.json() as Post).catch(err => { ...

What is the best way to preserve all props while typing a styled component in Typescript?

I'm just starting out with styled components and I want to ensure that I can properly type my styled components so that I can easily utilize all the props I pass, not just the ones defined in the theme or through an interface. Is there a way to achie ...

An array variable marked as mat-checked contains the total sum

Currently, I am utilizing mat-checked to calculate a total sum from an Array. The issue arises when the number of items in my array varies, triggering an error: ERROR TypeError: Cannot read property 'isChecked' of undefined Is there a way to ...

Formatting Time in Angular 2 Using Typescript

Upon reviewing my date source, I found the following: TimeR ="2017-02-17 19:50:11 UTC"; Within the HTML file, I implemented this code snippet <span class="text-lg">{{TimeR | date: 'hh:mm'}}</span> The current output displays the t ...

What is the best way to incorporate additional properties while utilizing useSession in Next.js with TypeScript?

I've encountered an issue while trying to add new properties using useSession() in a TypeScript environment. Although it works on console.log, there is an error related to the type mismatch. The useSession() function typically returns name, email, an ...

Exploring the @HostBinding argument in Angular directives

Need help grasping the concept behind the @Hostbinding argument: Snippet of the code: import { Directive, HostBinding } from "@angular/core"; @Directive({ selector: '[appDropdown]' }) export class DropdownDirective { @HostBinding(&apos ...

Setting the "status" of a queue: A step-by-step guide

I created a function to add a job to the queue with the following code: async addJob(someParameters: SomeParameters): Promise<void> { await this.saveToDb(someParameters); try { await this.jobQueue.add('job', ...

Execute a function that handles errors

I have a specific element that I would like to display in the event of an error while executing a graphql query (using Apollo's onError): export const ErrorContainer: React.FunctionComponent = () => { console.log('running container') ...

What is the best way to sort through an array depending on a specific sequence of elements provided

I am trying to create a custom pipe in Angular 5 that filters an array of events based on a given sequence. For instance, if my data is: ["submit", "click", "go_back", "click",...] I want to filter this data based on up to three inputs. If input ...

Executing asynchronous function in Angular using Typescript

My team and I are new to Angular and we are facing a challenge with invoking methods in sequence and returning a value. The issue is that the return statement is being executed before the completion of the execution process. We have tried various approac ...