Update tuple type with a new one

I have created the following code snippet and verified that it is functional:

function cases<K extends string, V, U, T>(map: { [key in K]: [V, U, T] }): [K, V, U, T][];
function cases<K extends string, V, U>(map: { [key in K]: [V, U] }): [K, V, U][];
function cases<K extends string, V>(map: { [key in K]: V }): [K, V][];
function cases<K extends string, V>(map: { [key in K]: V }) {
  return Object.keys(map).map(key => ([key] as any[]).concat(map[key as K]) as any);
}

for (const [key, arr, res] of cases({
    "abc": [[1, 2, "qqq"], 'qwe'],
    "def": [[4, 5, "asd"], 'www'],
})) {
    // const key: "abc" | "def"
    // const arr: (string | number)[]
    // const res: string
}

However, I am trying to avoid writing multiple overloads like this:

function cases<K extends string, V, U, T>(map: { [key in K]: [V, U, T] }): [K, V, U, T][];
function cases<K extends string, V, U>(map: { [key in K]: [V, U] }): [K, V, U][];
function cases<K extends string, V>(map: { [key in K]: V }): [K, V][];

and instead want to define a tuple type:

function cases<K extends string, V extends any[]>(map: { [key in K]: V }): [K, ...V] {

Unfortunately, it fails with an error message:

A rest element type must be an array type.

How can I resolve this issue?

Answer №1

The format [H, ...T] was initially suggested for usage but unfortunately is not currently supported. The inclusion of tuples in rest/spread positions in TypeScript version 3.0 provides an alternative approach to represent the same idea:

type Cons<H, T extends readonly any[]> =
  ((h: H, ...t: T) => void) extends ((...r: infer R) => void) ? R : never;

See how this can be applied:

type ConsTest = Cons<1, [2, 3, 4]> // [1, 2, 3, 4]

To define your cases() function with types:

function cases<K extends string, T extends any[]>(
  map: { [key in K]: T | [] }
): Array<Cons<K, T>> {
  return Object.keys(map).map(
    key => ([key] as any[]).concat(map[key as K]) as any
  );
}

The return type specified is Array<Cons<K, T>>, where T denotes the array type within the properties of the map parameter. Additionally, note that I made the property type in map to be T | [] instead of just T. This serves as a hint for the compiler to infer the type of map as a tuple if possible. This enables more accurate inference, especially when involving arrays like ["a", 1], ensuring they are recognized as tuples ([string, number]) rather than Array<string | number>. This adjustment may have resolved any issues you encountered while implementing this logic? Alternatively, you could utilize const assertions or other annotations to force the property types in map to become tuples.

Let's test it out to confirm its functionality:

for (const [key, arr, res] of cases({
  "abc": [[1, 2, "qqq"], 'qwe'],
  "def": [[4, 5, "asd"], 'www'],
})) {
  key; // "abc" | "def"
  arr; // (string | number) []
  res; // string
}

It appears everything is working correctly. Best of luck with your project!

Link to code

for (const [key, arr, res] of cases({
  "abc": [[1, 2, "qqq"], 'qwe'],
  "def": [[4, 5, "asd"], 'www'],
})) {
  key; // "abc" | "def"
  arr; // (string | number) []
  res; // string
}

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

Mastering the Manipulation of JSONObject and JSONArray in J2ME

As a newcomer to JSON programming in J2ME, I've come to understand that Json is utilized for data exchange much like XML. I am particularly interested in how to handle Array objects when converting between JSONtoObject and vice versa. The code snipp ...

Converting JSON data into a JavaScript array and storing it in a variable

Currently, I am delving into the world of JavaScript and my instructor has assigned a task that involves utilizing information from a JSON file within our JavaScript code. The issue I'm facing is deciphering how to effectively convert the JSON data i ...

What is the best way to integrate asynchronous computed observable with several concurrent $.ajax requests?

I'm currently working on implementing an asynchronous computed observable following the guide provided here. While I have successfully achieved this for a single ajax call, I am facing a challenge in figuring out how to perform multiple ajax calls in ...

Navigating the realm of Ionic Storage: mastering simplicity within the realm of Promises

Using Ionic Storage has been quite challenging for me as it returns a Promise, which I find to be impractical. I am trying to retrieve a value from Storage and based on its boolean value, perform certain actions. In my old Angular 1 code, I had the follo ...

What is the best method to retrieve a specific element from a json array within postgresql?

https://i.sstatic.net/4Z9iW.pngIn my table parameter, there are 2 columns: id (integer) and param_specs (text). The actual param_specs column is structured as shown below: param_specs [ {"paramName":"param1", "type":"string", "defaultValue":"tomcat7", ...

What is the importance of injecting a service through a constructor in Angular 2?

I've been diving into Angular 2 and finding myself puzzled by the constructor. Let's take a look at the following code snippet: import { Component, OnInit } from '@angular/core'; import { FormGroup,FormsModule,FormControl } from &apos ...

Convert an object to nested JSON in Angular 5

I am struggling with using Angular 5 HttpClient to send a post request because I am having trouble casting an object to nested JSON. For instance, I have the following class: export class Team { members: Person[]; constructor(members: Person[]) ...

Having trouble accessing array value in Reactjs - returning undefined

I am currently in the process of comparing values from 2 different arrays that contain state data. However, I am encountering an issue where the value of otherItems[i] is returning as undefined. To provide some context, the array Items consists of Objects ...

When attempting to access the Angular Component, a 127.0.0.1 error indicating that the page was not found

After successfully building my Angular Application using ng build --prod and serving it with http-server -o, I encountered a sudden issue. Now, every time my app tries to load a new component, I receive a 404 error. I have attempted various solutions such ...

the undefined 'pipe' cannot be read

Trying to perform unit testing for an Angular component is a new experience for me. Currently, I am encountering a specific issue that I would like assistance with. The component in question contains the following select statement: this.store.select(getI ...

Mapping objects in an array with React.js

I have a JavaScript file that I am attempting to map. I want to map it to specific buttons, but I am having trouble with it. Can you please help me? I have tried several options, but nothing seems to work in my case {DlCards.map((dvlcards, cardtitle, link ...

Is my solution handling exceptions properly in corner cases?

Given an array in which I need to print the first index of a repeating element using recursion and binary search. However, there is a corner case where if the element is at index 0, it throws an "ArrayIsOutOfBound" exception. This issue occurs in every sol ...

What is the best way to merge two nested arrays of objects in JavaScript that share a common parent?

Hello everyone, I am facing an issue when trying to combine two nested parent arrays of objects. I want to merge only the children items that have the same group parent. Here is my scenario: I have two arrays var arr1 = [{group: "a", items: [&quo ...

The types definition for OpenSeadragon is lacking a property

I have developed an application using React Typescript and have integrated OpenSeadragon () for displaying images. To incorporate type definitions for OpenSeadragon, I am utilizing @types/openseadragon: https://www.npmjs.com/package/@types/openseadragon M ...

Having trouble with [at-loader] while incorporating Typescript and react-bootstrap in webpack?

While working with webpack, I encountered an error message when using a component in react-bootstrap along with typescript. The error displayed is as follows: ERROR in [at-loader] ./node_modules/react-bootstrap/esm/NavbarCollapse.d.ts:4:18 TS2320: ...

Disable dates that are more than 7 days from the current date using Material UI's Date

How can I restrict users from selecting dates more than 7 days after their initial selection? In the example image provided, the date of January 30th should be disabled for selection. https://i.stack.imgur.com/iTem4.png Below is the code snippet: const ...

Is it possible to return an empty array within an HttpInterceptor when encountering an error?

When encountering errors that require displaying empty "lists" in dropdowns, I utilize this interceptor: public intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { return next.handle(request).pipe(catchEr ...

What steps can I take to fix the ESM / require error while using TypeScript 4.8?

My Node.js application uses TS 4.8, and I recently updated the file-type package. However, after the update, my project compilation fails with the following error: [1] const _fileType = /#PURE/ _interopRequireWildcard(require("file-type")); [1] ...

What is the best way to see if a variable is present in TypeScript?

I am facing an issue with my code that involves a looping mechanism. Specifically, I need to initialize a variable called 'one' within the loop. In order to achieve this, I first check if the variable exists and only then proceed to initialize it ...

Enabling Typescript to identify additional methods introduced via Object.prototype

I am hoping for typescript to detect the changes I make to Object.prototype. Ideally, I want to be able to do something like: Object.prototype.l = function (title: string) => { console.log({[title]: this}) return this } const bar = foo().l(&apos ...