TypeScript combines strong typing for arrays into a unified array of objects

I developed a JavaScript function that can merge multiple arrays into an array of objects based on provided key names. Here’s an example:

const mergeArraysToSeries = (arrs, keys) => {
  const merged = [];

  for (let dataIndex = 0; dataIndex < arrs[0].length; dataIndex++) {
    const el = keys.reduce((combined, currKey, keyIndex) => {
      const val = arrs[keyIndex][dataIndex];
      return { ...combined, [currKey]: val };
    }, {});
  
    merged.push(el);
  }

  return merged;
}

const example = mergeArraysToSeries([[1,2,3], ['a','b','c']], ['num', 'letter'])
// example = [{num: 1, letter: 'a'}, {num: 2, letter: 'b'}, {num: 3, letter: 'c'}] 

I am now looking to enhance this function with TypeScript to achieve autocomplete on the merged array and ensure type safety for each key. Is there a way to accomplish this without relying on any types?

The current type signature I have is:

const mergeArrayToSeries = <K>(arrs: any[][], keys: (keyof K)[]): Record<keyof K, any>[] => ...

I would like to eliminate the usage of any for passed arrays while maintaining type safety. Any suggestions on how to achieve this?

Thank you!

Edit: The goal is to make this work seamlessly for merging any number of arrays together.

Answer №1

If you're looking to combine arrays into a series, you can employ a function like the one below:

declare function mergeArraysToSeries<
  T extends any[],
  U extends any[],
  P1 extends string,
  P2 extends string
>(arrays: [T, U], properties: [P1, P2]): {
    [K in P1]: T[number]
  } & {
    [K in P2]: U[number]
  }[];

const example = mergeArraysToSeries([[1,2,3], ['a','b','c']], ['num', 'letter']); // example is { num: number; letter: string }[]

Playground link

Additional Information

To accommodate more than two arrays, you can include additional overloads as shown below.

declare function mergeArraysToSeries<T, U, P extends readonly string[]>(arrays: [T[], U[]], properties: P): { [K in P[0]]: T } & { [K in P[1]]: U }[]
declare function mergeArraysToSeries<T, U, V, P extends readonly string[]>(arrays: [T[], U[], V[]], properties: P): { [K in P[0]]: T } & { [K in P[1]]: U } & { [K in P[2]]: V }[]
declare function mergeArraysToSeries<T, U, V, W, P extends readonly string[]>(arrays: [T[], U[], V[], W[]], properties: P): { [K in P[0]]: T } & { [K in P[1]]: U } & { [K in P[2]]: V } & { [K in P[3]]: W }[]

const two = mergeArraysToSeries([[1, 2, 3], ['a', 'b', 'c']], ['num', 'letter'] as const)
const three = mergeArraysToSeries([[1, 2, 3], ['a', 'b', 'c'], ['foo', 'bar', 'baz']], ['num', 'letter', 'other'] as const)
const four = mergeArraysToSeries([[1, 2, 3], ['a', 'b', 'c'], ['foo', 'bar', 'baz'], [0, 0, 0]], ['num', 'letter', 'other', 'index'] as const)

Playground link

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

Custom React component - DataGrid

Just starting out in the world of React and attempting to create a custom component with parameters. I'm curious about the correct approach for achieving this. Here's my current code snippet - how do I properly pass Columns, ajax, and datasourc ...

Every time I attempt to destructure the state object in react typescript, I encounter the error message stating 'Object is possibly undefined'

Whenever I attempt to destructure my state object in react typescript, I encounter an error stating Object is possibly 'undefined'. When I try using optional chaining, a different error pops up saying const newUser: NewUser | undefined Argument o ...

In React Router v6, you can now include a custom parameter in createBrowserRouter

Hey there! I'm currently diving into react router v6 and struggling to add custom params in the route object. Unfortunately, I haven't been able to find any examples of how to do it. const AdminRoutes: FunctionComponent = () => { const ...

What is the best method for accessing a store in Next.js with Redux Toolkit?

Currently, I am working on incorporating integration testing for my application using Jest. To achieve this, I need to render components in order to interact with various queries. However, in order to render a component, it must be wrapped in a Provider to ...

Dealing with circular dependencies in NestJS by using ForwardRef

Hey everyone, I've been running into a circular dependency issue with NestJS. I tried using the forwardref method, but it hasn't resolved the problem for me. // AuthModule @Module({ imports: [ forwardRef(() => UserModule), JwtModule ...

What is the best way to create a personalized filter function for dates in JavaScript?

I am working with a DataTable that includes a column called Timestamp: <p-dataTable sortMode="multiple" scrollable="scrollable" scrollHeight="150" [value]="currentChartData" #dt> <p-column field="timestamp" header="Timestamp" [sortable]=" ...

Is there a way to access and read an Excel file stored within the assets folder using Angular?

I need assistance converting an excel file to a JSON format. My excel file is currently stored in the assets folder, and I am looking for guidance on how to access it from app.component.ts. Any help would be greatly appreciated! ...

Unable to access current props within useEffect block

When I use useEffect with the parameter props.quizStep, my function fn (which is a keydown event listener) is unable to access the current value of props.quizStep. I'm puzzled as to why it's not working properly. Can you help me understand? Bel ...

Querying Cloud Firestore with User ID

I'm facing an issue with retrieving a subset of data based on the first letter of the name and including the UID of the document. No matter what I try, it just returns empty data. fetchDataByFirstLetter(firstLetter: string) { this.afs.collection(&a ...

Generate several invoices with just a single click using TypeScript

I'm interested in efficiently printing multiple custom HTML invoices with just one click, similar to this example: Although I attempted to achieve this functionality using the following method, it appears to be incorrect as it prompts the print dialo ...

Exploring the world of typescript with the power of ts-check

I'm having trouble figuring out how to work with a generic function using TypeScript's new ts-check feature. /** * @type {Reducer<IPoiState, any>} */ const poi = handleActions({ [ADD_BOOKMARK_START]: (state) => { return { ...sta ...

Node.js server containerized with Docker: deleted express route remains accessible

I recently developed a Twitch Chat Bot using Dockerized (docker compose), Node.js v16 with express. To create an authorize-page for users to authorize my bot on the Twitch API, I utilized the route /auth/request: this.serverUrl = serverUrl; this.port = po ...

Is the detection change triggered when default TS/JS Data types methods are called within an HTML template?

I'm currently updating an application where developers originally included function calls directly in the HTML templating, like this: <span>{{'getX()'}}</span> This resulted in the getX method being called after each change dete ...

What steps should I take to ensure that TypeScript acknowledges the validity of my object assignment?

Trying to implement this code: type A = { b: false, } | { b: true, p: string; } function createA(b: boolean, p: string | undefined): A { if (b && p === undefined) { throw 'Error'; } const a: A = { b, ...

Angular 8 throws a TS2339 error, yet the code is functioning perfectly and delivering the desired output

Upon compiling my code, I encountered the following error: ERROR in src/app/home/home.component.ts:13:37 - error TS2339: Property 'name' does not exist on type 'string | Type'. Property 'name' does not exist on type &ap ...

Issue encountered when attempting to access disk JSON data: 404 error code detected

I am attempting to retrieve JSON data from the disk using a service: import { Product } from './../models/Product'; import { Injectable } from '@angular/core'; import { Observable } from 'rxjs'; import { HttpClient } from &apo ...

Tips for enabling the TypeScript compiler to locate bokeh's "*.d.ts" files

I recently made the switch from Bokeh's convenient inline extension framework to their npm based out of line build system. I'm currently working on getting my extension to build, but I've noticed that Bokeh organizes all TypeScript *.ts.d fi ...

Error: The function to create deep copies of objects is not working properly due to TypeError: Object(...) is not a

Encountering a TypeError: Object(...) is not a function in the following situation: To set up the state of a component with a specific Article (to be fetched from the backend in componentDidMount), I am implementing this approach // ArticlePage.tsx import ...

Retrieve the file from the REST API without using the window.open method

I'm looking for a method to download files from an API without using window.open(). I want the download process to start immediately upon calling the API. Currently, I am downloading an .xls file generated by a REST API using window.open() API Endpo ...

Utilize an exported class as a type within a .d.ts file

I have two classes, ./class1.ts and ./class2.ts, with the following structure: export class Class1{ ... } and export class Class2{ ... } In my file ./run.ts, there is a function that accepts a class input function doSomething(klass: ClassType){ l ...