What is the best way to transform an array into an object and have it return a specific data

Trying to determine the argument type, but unsure of the next steps

function convertArrayToObject(keys) {
    return keys.reduce((prev, key) => ({ ...prev, [key]: key}), {})
}

const output = convertArrayToObject(['aa', 'bb']);
// expected output type : `{ aa: string, bb: string }`

Answer №1

To prevent the compiler from widening the type of the passed array to string[], you will need to utilize const type parameter.

It's important to note that const type parameters are only available in Typescript version 5.0. In versions prior to that, a possible solution, although a bit cumbersome, is to use const assertion, as demonstrated in @Behemoth's answer.

function convertArrayToObject<const T extends readonly string[]>(keys: T) {}

Once that is in place, the type for the reduce function needs to be defined. It should be an object where the keys are the elements of the array and the values are regular strings.

To determine the type of elements, indexed access is required:

// 'aa' | 'bb'
type Case1 = ['aa', 'bb'][number]

Adapting this concept to fit our required object:

// type Case2 = {
//     aa: string;
//     bb: string;
// }
type Case2 = {[K in ['aa', 'bb'][number]]: string}

Looking good so far!

We then need to assert the initial value of the reduce function to this type:

function convertArrayToObject<const T extends readonly string[]>(keys: T) {
  return keys.reduce((prev, key) => ({ ...prev, [key]: key }), {} as {[K in T[number]]: string});
}

For testing purposes:

// const result: {
//     aa: string;
//     bb: string;
// }
const result = convertArrayToObject(['aa', 'bb']);

Try it out in the playground

Answer №2

To enhance the functionality of the convertArrayToObject() method, you can modify it to accept a generic parameter that will help infer the return type. However, to ensure compatibility, you will need to employ Type Assertion for the initial value in the .reduce() method to align with the return type. It is essential to specify your argument array as const so that the values can be accurately inferred as more than just string data types.

function convertArrayToObject<T extends readonly string[]>(
  keys: T
): {[K in T[number]]: string} {
  return keys.reduce(
    (prev, key) => ({...prev, [key]: key}),
    {} as {[K in T[number]]: string}
  );
}


const result = convertArrayToObject(["aa", "bb"] as const);
//    ^? const result: { aa: string; bb: string; }

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

What is the most effective method for sharing a form across various components in Angular 5?

I have a primary form within a service named "MainService" (the actual form is much lengthier). Here is an overview- export class MainService { this.mainForm = this.formBuilder.group({ A: ['', Validators.required], B: & ...

Enhancing Web Service Calls with Angular 2 - The Power of Chaining

I am currently facing an issue where I need to make multiple web service calls in a sequence, but the problem is that the second call is being made before the .subscribe function of the first call executes. This is causing delays in setting the value of th ...

Manipulating variables across various methods in TypeScript

I have a simple code snippet where two variables are defined in the Main method and I need to access them from another method. However, I am encountering an issue with 'variables are not defined', even though I specified them in the declerations ...

What is the process for retrieving the GitHub username in the GitHub OAuth Next.js sign-in callback in order to store it in a database?

1. Detail the issue I am facing a challenge while developing a Full Stack Website using Next.js and Typescript. Specifically, I am having difficulty persisting the Github Username in the database when a user signs in via Github OAuth. Should I consider st ...

Modify the selected toggle buttons' color by utilizing the MUI ThemeProvider

I am currently working on customizing the color of selected toggle buttons within my React app using TypeScript and ThemeProvider from @mui/material 5.11.13. Despite my efforts, when a toggle button is selected, it still retains the default color #1976d2, ...

Best practices for customizing Material UI v5 Switch using Theme

I've successfully implemented a Material Switch based on my design by creating a custom component and styling it using the styled and sx prop. However, I'm interested in figuring out how to achieve the same result within the theme itself so that ...

There seems to be an issue with the response type in the node.js environment

I am currently working on node.js and typescript, but I am encountering a minor issue. Below is the routeController I have created: public allUsers = (req: Request, res: Response) => { res.status(500).json({ status: "ERROR", ...

In Angular 17, is there a way to trigger a component's method when a Signal is modified?

Our component is designed to monitor signals from a Service: export class PaginationComponent { private readonly pageSize = this.listService.pageSize.asReadonly(); private readonly totalCount = this.listService.totalCount.asReadonly(); readonly pag ...

Looking to incorporate an additional column 'LastName' that can be used for filtering in the Angular data table code. This column will be included if it is present in the data

function applyFilter(filterValue: string) { filterValue = filterValue.toLowerCase(); --- return filtered result return this.dataSet.filter( (item: any) => item.name ? item.name.toLowerCase(). ...

How can we fetch data from the server in Vue 2.0 before the component is actually mounted?

Can anyone help me with this question noted in the title? How can I prevent a component from mounting in <router-view> until it receives data from the server, or how can I fetch the data before the component is mounted in <router-view>? Here a ...

Angular 8 does not allow for the assignment of type '{}' to a parameter

I have a unique approach for managing errors: private handleErrors<T>(operation = 'operation', result?: T) { return (error: any): Observable<T> => { console.error(error); this.record(`${operation} failed: ${error.m ...

What are the steps to incorporating a personalized component into an extension?

I am working on a TypeScript file that includes a class inheriting cc.Component. My goal is to package this file as an extension and make it easily accessible within the editor, allowing users to add it to a node with ease. What steps should I take to ac ...

What is the best way to utilize mapping and filtering distinct values in an array using TypeScript?

What is the best way to filter and map distinct elements from an array into another array? I've experimented with various methods but keep encountering a syntax error stating "Illegal return statement". My objective is to display only unique items f ...

What is the best way to convert JSON into a complex object in Typescript and Angular?

In my Typescript class for an Angular version 5 project, I have a JavaScript function that generates a style object. Here is the function: private createCircle(parameters: any): any { return new Circle({ radius: parameters.radius, ...

Accessing different pages in Angular 2 based on user type

If I have four pages and two user types, how can we implement access control in Angular 2 so that one user can access all four pages while the other is restricted to only two pages? ...

Different approach to including labels on scatter plot without relying on "chartjs-plugin-datalabels"

I need help adding labels to the pink scatter dots without affecting the green bars in the horizontal bar chart generated by ngchart. You can see an image of the chart here. Whenever I try to include the following code: import ChartDataLabels from "c ...

Exploring the potential of Socket.io and Angular with the seamless integration of

I have encountered an issue regarding the use of async pipe with Observables. Initially, I assumed that returning an Observable from my service on a socket.on event would suffice. However, it appears that my approach is incorrect. Can you guide me on the c ...

turning off next.js server side rendering in order to avoid potential window is undefined issues

I am currently managing a private NPM package that is utilized in my Next.js project, both of which are React and Typescript based. Recently, I integrated a graph feature into the NPM package and encountered an issue where any reference to window within t ...

Experimenting with Cesium using Jasmine (Angular TypeScript)

I have a TypeScript app built using Angular that incorporates Cesium: cesium-container.component.ts import { Component, ElementRef } from '@angular/core'; import { Viewer } from 'cesium'; import { SomeOtherCesiumService } from 'sr ...

Using `location.reload()` and `location.replace(url)` does not seem to function properly when using Electron with Angular

Using Electron to rebuild a pre-existing web app, the main.js file in electron is kept simple: // Modules to control application life and create native browser window const {app, BrowserWindow} = require('electron') // Keep a global reference o ...