Change an array of objects into a map where each object is indexed by a unique key

I'm attempting to transform an array of objects into a map, with the index based on a specific attribute value of the object in typescript 4.1.5

Additionally, I am only interested in attributes of a certain type (in this case, string)

A similar question was posed in javascript here : Convert object array to hash map, indexed by an attribute value of the Object

type Foo = {
        a : string
        b : number
}

const foos: Foo[] = []
// should only propose to index by 'a'
const foos_indexed_by_a = indexArrayByKey(foos, 'a')

function indexArrayByKey<T> (array: T[], key: Extract<keyof T, string>): Map<string, T> {
        return array.reduce((map, obj) => map.set(obj[key], obj), new Map<string, T>())
}

Playground Link

Currently, I am facing an issue accessing the property key of obj (resulting in a compilation error)

Thank you for your assistance :)

Answer №1

In order to narrow down the keys based on those with a string value, the Extract method should not be used as it filters out keys that are strings (excluding numbers or symbols). Instead, you can utilize the KeyOfType function as outlined here

type KeyOfType<T, V> = keyof {
    [P in keyof T as T[P] extends V? P: never]: any
}
function indexArrayByKey<T, K extends KeyOfType<T, string>> (array: T[], key: K): Map<T[K], T> {
        return array.reduce((map, obj) => map.set(obj[key], obj), new Map<T[K], T>())
}

Playground Link

We opt for T[K] over string because T[K] could potentially be a subtype of string, prompting TypeScript to raise an error with string. However, in most scenarios, this approach should work seamlessly.

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 '{ children: Element; }' is lacking the specified properties within type - NextJS version 13.0.6 with TypeScript version 4.9.3

Currently, I am delving into NextJS / TypeScript and have come across a type error. The component structure is as follows: interface LayoutProps { children: React.ReactNode; title: string; keywords: string; description: string; } const Lay ...

Dynamically assign values to object properties of varying data types using indexing

My goal is to dynamically update one object using another object of the same type. This object contains properties of different types: type TypeOne = 'good' | 'okay'; type TypeTwo = 'default' | 'one'; interface Opt ...

Shifting the use of @Inject(MAT_DIALOG_DATA) away from class constructors

Our team is making a transition in the Dependency Injection pattern we utilize to minimize the dependency on TypeScript constructors. This shift will help us address recurring issues caused by team members adding logic that shouldn't be included in co ...

Mastering Angular 7: A guide to efficiently binding values to radio buttons

Struggling to incorporate radio buttons into my project, I encountered an issue where the first radio button couldn't be checked programmatically. Despite attempting the suggested Solution, it didn't resolve the problem within my code. Below is ...

Error message: "The toJSON method is not found for the item in the nested array of

Encountering an issue with NSwag in my Angular project where it throws an error when attempting to send data if the object contains a nested array of objects like this: export interface IJobAdDto { mainJobAd: JobAddDetailsDto; differentLanguageJobA ...

What is the best way to monitor parameter changes in a nested route?

I need assistance with managing routes const routes: Routes = [ { path: 'home', component: HomeComponent }, { path: 'explore', component: ExploreComponent, children: [ { path: '', component: ProductListC ...

How can you implement Higher Order Components as a decorator in TypeScript?

Currently, I am attempting to develop a decorator that accepts an argument from React's Context provider. When creating a higher-order component (HOC), the process is straightforward: interface DashboardProps { user: User; } class Dashboard exten ...

Adjust the tally of search results and modify the selection depending on the frequency of the user's searches within an array of objects

Seeking assistance with adding a new function that allows users to navigate to the next searched result. Big thanks to @ggorlen for aiding in the recursive search. https://i.stack.imgur.com/OsZOh.png I have a recursive search method that marks the first ...

Calculating the frequency of a variable within a nested object in an Angular application

After assigning data fetched from an API to a variable called todayData, I noticed that there is a nested object named meals within it, which contains a property called name. My goal is to determine the frequency of occurrences in the name property within ...

What is the best way to dynamically validate the fields and generate an array?

Currently in my Angular application, I've successfully implemented a pivot table using pivot.js. Now, I am faced with the task of loading all the indexes from elastic search whenever the user switches the index. Once the index is changed, the corresp ...

Is there a way to transform an HTMLCollection into an array without depleting it of its elements?

I've been attempting to transform a collection of 4 divs in HTML into an array, but all my efforts seem to lead to the array becoming void. <div class="container"> <div class="shape" id="one"></div> <div class="sh ...

Setting an initial value for an @Output EventEmitter in Angular 6 is a breeze

I'm working on a component that includes a dropdown selection menu. <p style="padding: 5px"> <select [(ngModel)]='thisDD' name="nameDD" id="idDD" (ngModelChange)="updateDD(thisDD)" class="form-control"> <o ...

Transform Material UI Typography to css-in-js with styled-components

Can Material UI elements be converted to styled-components? <Container component="main" maxWidth="XS"> <Typography component="h1" variant="h5"> Sign in </Typography> I attempted this for typography but noticed that t ...

Integrate TypeScript into the current project

As a newcomer to Typescript, I am currently exploring the option of integrating it into my current project. In our MVC project, we have a single file that houses the definitions of all model objects. This file is downloaded to the client when the user fir ...

Creating a custom event handler for form input changes using React hooks

A unique React hook was created specifically for managing form elements. This hook provides access to the current state of form fields and a factory for generating change handlers. While it works seamlessly with text inputs, there is a need to modify the c ...

Sending data using formData across multiple levels of a model in Angular

I have a model that I need to fill with data and send it to the server : export interface AddAlbumeModel { name: string; gener: string; signer: string; albumeProfile:any; albumPoster:any; tracks:TrackMode ...

Utilize React Native to continuously fetch and display data from this API

[React-Native] Seeking assistance on looping through JSON API for conditional rendering. As a beginner, I would greatly appreciate your guidance. Thank you. Find my code here: https://drive.google.com/file/d/0B3x6OW2-ZXs6SGgxWmtFTFRHV00/view Check out th ...

SWIFT functions with arrays and dictionary data structures

My goal is to transfer information to the second controller via a segue from the array: var gists = [Gists]() Here is how I have implemented the prepare(for segue: method: override func prepare(for segue: UIStoryboardSegue, sender: Any?) { if se ...

Before computing the width, Next.js Swiper slide occupies the entire width

Check out the code snippet below: 'use client'; import { Swiper, SwiperSlide } from 'swiper/react'; import 'swiper/css'; import 'swiper/css/pagination'; export default function Component() { const cards = [{ id: 0 ...

Exploring the Differences Between Arrays of Objects and Arrays in JavaScript

While working on a project for a client, I encountered an interesting problem. I have two arrays - one with objects and one with values. The task is to populate the array of objects with new objects for every item in the value array. To clarify, here is th ...