What is the process for obtaining a flattened tuple type from a tuple comprised of nested tuples?

Suppose I have a tuple comprised of additional tuples:

type Data = [[3,5,7], [4,9], [0,1,10,9]];

I am looking to develop a utility type called Merge<T> in such a way that Merge<Data> outputs:

type MergedData = Merge<Data>;
// type MergedData = [3,5,7,4,9,0,1,10,9];

For this scenario, it is safe to assume that the tuples are only nested one level deep. The size of the tuples can vary.

What would be the best approach to achieve this?

Answer №1

If you want to achieve this, you would need recursive conditional types. This feature will be fully available in version 4.1.

type Example = [[3,5,7], [4,9], [0,1,10,9]];
type Flatten<T extends any[]> = 
    T extends [infer U, ...infer R] ? U extends any[] ? [...U, ... Flatten<R>]: []: []
type FlatExample = Flatten<Example>;

Playground Link

Edit

A simpler version, courtesy of jcalz:

type Example = [[3,5,7], [4,9], [0,1,10,9]];
type Flatten<T extends any[]> = 
    T extends [any, ...infer R] ? [...T[0], ... Flatten<R>]:  []
type FlatExample = Flatten<Example>;

Playground Link

/Edit

You can implement a workaround even now (the extra level of indirection is necessary to trick the compiler into accepting the recursive conditional type; conceptually, it is similar to the simplified version above):

type Example = [[3, 5, 7], [4, 9], [0, 1, 10, 9]];
type Flatten<T extends any[]> = T extends [infer U, ...infer R] ? {
    1: U extends any[] ? [...U, ...Flatten<R>] : [],
    2: []
}[U extends any[] ? 1 : 2] : [];

type FlatExample = Flatten<Example>;

Playground Link

Just for fun, here's the generalized flattening version for 4.1.

type Example = [[3,5,7], [4,9, [10, 12, [10, 12]]], [0,1,10,9, [10, 12]]];
type Flatten<T extends any[]> = 
    T extends [infer U, ...infer R] ? 
        U extends any[] ? 
        [...Flatten<U>, ... Flatten<R>]: [U, ... Flatten<R>]: []
type FlatExample = Flatten<Example>;

Playground Link

Note: Although recursive types are more supported in 4.1, keep in mind that you may still encounter hardcoded limits in the compiler, such as type instantiation depth and total type instances. Recursive types tend to generate a large number of type instantiations, so use them judiciously.

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

What is the method for determining the type of a TypeScript class member that is associated with a commonly used symbol such as Symbol.toStringTag?

Does anyone know the correct TS syntax for extracting the type of a class method indexed with a well-known Symbol? Here are two incorrect methods: type T = String[Symbol.toStringTag]; // 'Symbol' only refers to a type, but is being used as a name ...

Why does the implementation of my interface differ from what is specified in the TypeScript documentation?

Currently delving into the world of TypeScript documentation https://www.typescriptlang.org/docs/handbook/2/classes.html Specifically focusing on the section implements Clauses, an interesting revelation surfaces: A Word of Caution It’s worth noting t ...

The element is absent in Type {}, however, it is mandatory in Type '&' and '&' cannot be designated to String Index Type Errors

I have a goal of passing the logged-in user's email address to a 'dict' as a key, fetching its corresponding token value, and using it as a query parameter for an API call. The user's email is retrieved from the user data upon login, sp ...

Access NgModel from NgForm

Is there a way to access the NgModel of a FormControl retrieved from the NgForm.controls object within its parent form, or directly from the form itself? Upon form submission, I pass the form as a parameter to a custom function: <form #myForm="ngForm" ...

Angular and Spring setup not showing data despite enabling Cross Origin Support

I'm currently in the process of developing a full stack application using Spring and Angular. After successfully setting up my REST APIs which are functioning properly on port 8080, I encountered an issue when trying to access them from my frontend ( ...

Typescript MUI Autocomplete: Can you specify the parameter type of the PaperComponents function?

If you use MUI's Autocomplete, there is a property called PaperCompomponent that allows you to pass your own react component. This property is a function with properties as a parameter, which can then be used to pass on to your custom component. In T ...

Issue with React TSX component in NextJs 14.0.4: Local MP3 files cannot be played, only external online MP3 files work

I have created a component that wraps around HTML audio and source tags. It functions perfectly when playing mp3 files from an external source, like this sound clip . However, it returns a GET 404 error when trying to access local mp3 files. Can anyone exp ...

Is React Typescript compatible with Internet Explorer 11?

As I have multiple React applications functioning in Internet Explorer 11 (with polyfills), my intention is to incorporate TypeScript into my upcoming projects. Following the same technologies and concepts from my previous apps, I built my first one using ...

Iterating through an array with ngFor to display each item based on its index

I'm working with an ngFor loop that iterates through a list of objects known as configs and displays data for each object. In addition to the configs list, I have an array in my TypeScript file that I want to include in the display. This array always ...

Question about TypeScript annotations: arrays containing key-value pairs

Is there an explanation for why this issue occurs in VSCode? interface Point { x: number; y: number; } let grid: [key: number, value: [key: number, value: Point]]; // ... // Accessing an object of type number | [key: number, value: Point] var c ...

Material-UI: Tips for aligning pagination button in the center

My attempt to implement Pagination using Material-UI went well, but now I am struggling to center the arrow buttons and page numbers. I initially tried centering them by wrapping them in a <div style={{textAlign: "center"}}>, however this ...

React Router is used to render routes that do not match the specified path

I am utilizing TypeScript in React Router. I have defined two routes: / and /pages/id. class MyComponent extends React.Component { render() { return <BrowserRouter> <div> <Route exact path='/' ch ...

Exploring the process of importing and exporting modules in TypeScript with the help of systemjs

Is there a way to export a module using systemjs in TypeScript? I encountered the error: TS1148 cannot compile modules unless the '--module' flag is provided. Here's my code; animal.ts export class Animal { color: string; age: numb ...

The repository injected into NestJs using TypeORM suddenly becomes null

In my code, I am fetching Requisition data from an external system using the following approach: init() { const requisitionData = this.loginMb().pipe( map(response => response.data.token), switchMap(loginData => this.getRequisitions(loginD ...

My worker threads seem to be flying under the radar

Currently, I am working on implementing worker threads into my Node.js/Typescript application. I have made significant progress, but it appears that my worker threads are not being executed as expected. Despite adding loggers inside the function intended f ...

Ensuring Type Compatibility Between Classes and Object Literals in TypeScript

When working with TypeScript, it is important to note that an object literal can be assigned to a class typed variable as long as the object provides all properties and methods required by the class. class MyClass { a: number; b: string; } // The co ...

Exploring the differences in object shapes using TypeScript

I'm currently working on defining an object that has the ability to hold either data or an error. export type ResultContainer = { data: any; } | { error: any; }; function exampleFunction():ResultContainer { return { data: 3 } } ...

Can you please provide information on the specific type of decorator used in Vuex, known as the 'vuex-class' decorator

My TypeScript project has the 'no-implicit-any' rule enabled, but I'm facing challenges when it comes to defining types for all of the 'vuex-class' decorators. For instance, when importing the namespaced action @(namespace('f ...

Building Silent Authentication in React Native with the help of Auth0: A Step-by-Step Guide

I am currently working on my first React Native app, and I have integrated Auth0 for authentication purposes. My goal is to implement silent authentication using refresh tokens. So far, I have attempted to use the checkSession() method but encountered an ...

What is the Typescript compiler utilized by Visual Studio 2015 when compiling on save?

Currently using Visual Studio 2015 Update 3 with TypeScript 2 for VS installed. I have a basic ASP.NET Core MVC web application with a few simple TypeScript files. The project contains a tsconfig.json file in the root folder with "compileOnSave": true. I ...