Dealing with dynamic grouping of results in JavaScript using Typescript

Currently, I have a JSON endpoint that returns data in the following format:

const tags = [
        {
            "name": "advertiser id",
            "id": "12345",
            "data_type": "output_type"
        },
        {
            "name": "advertiser id",
            "id": "345678",
            "data_type": "output_type"
        },
         {
            "name": "my name",
            "id": "564563",
            "data_type": "input_type"
        },
    
    ]

The JSON contains multiple "data_types", with different forms. Currently, there are output_type **(2)** and input_type **(1)**, but this could vary greatly. To simplify the frontend, I am grouping this data.

Using Lodash:

const grouped = _.groupBy(tags, tag => tag.data_type);

In simplicity, using something similar to the above code snippet in Lodash, the data type will become a key, resulting in the desired JSON structure:

const tags = {
        output_type: [{
            "name": "advertiser id",
            "id": "12345",
        },
        {
            "name": "advertiser id",
            "id": "345678",
        }],
    
        input_type: [
         {
            "name": "my name",
            "id": "564563",
        }],

    }

An example of how I would implement this in TypeScript:

export interface TagDefinition {
  name: string;
  id: string;
}

export interface GroupedTags {
  output_type: TagDefinition[];
  input_type: TagDefinition[];
}

export interface TagsState {
  tags: Tags[];
  groupedTags: GroupedTags;
  error?: Error;
}

My concern is about the flexibility of my current approach. Since the endpoint can return any data_type at any time, having predefined keys like 'output_type' and 'input_type' may not be dynamic enough. I'm exploring if there's a way, possibly using Generics, to make this more adaptable. Any suggestions on what this could look like?

edit I believe

Dictionary<ToolDefinition[]>
might be the solution, but I'm not entirely certain.

Answer №1

When considering the structure of your data:

type Information = {
 title: string;
 reference: string;
 category: "user_input" | "system_output";
};

This approach should help you get started:

type GroupedData<D, Key extends keyof D> = D[Key] extends PropertyKey ? Record<D[Key], D[]> : never; 

type ResultInfo = GroupedData<Information, "category">;// -> { user_input: Information[]; system_output: Information[]; }

If you wish to exclude the common key, Key, from D:

type GroupedExcludeKey<D, Key extends keyof D> = D[Key] extends PropertyKey ? Record<D[Key], Pick<D, Exclude<keyof D, Key>>[]> : never;

type ExcludedKeyResult = GroupedExcludeKey<Information, "category">; // -> { user_input: Array<{ title: string; reference: string; }>; system_output: Array<{ title: string; reference: string; }>; }

Answer №2

My recommendation would be to opt for

Dictionary<string, List<TagDefinition>>
. This way, you can seamlessly transform the incoming data by utilizing the data_type as the unique identifier and then populating it with the necessary attributes.

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

Does the Angular CanLoad guard only trigger once during the initial lazy load?

Recently, I've come across an interesting issue within my Angular application that consists of lazy-loaded modules. In one specific module, there is a guard in place to verify if the user decoded from the JWT token is a system admin. If the user meet ...

Issue with <BrowserRouter>: TS2769: No suitable overload for this call available

I encountered this error and have been unable to find a solution online. As a beginner in typescript, I am struggling to resolve it. The project was originally in JavaScript and is now being migrated to TypeScript using ts-migrate. I am currently fixing er ...

Ways to pass functions as properties to a React custom modal?

I'm currently working on a React login page setup. The login functionality is embedded in a Modal using the React-Modal library. When a user presses the login button, data is supposed to be sent to a Custom Modal as props to display a notification win ...

Mapping JSON to interface in Angular 7: A step-by-step guide

I am currently working with angular7 and I have a requirement to map a json object to my interface. My goal is to create a function that can accurately map the fields of the json object to the corresponding properties in the interface. Additionally, if the ...

Enforcement of Class Initialization in Typescript 2.7

After initializing a sample project using the Angular template in Visual Studio 2017, I made sure to update the package.json file with the latest module versions. However, upon executing the npm install command and navigating to the site, an error related ...

Tips on providing form validation in Ionic

I'm currently working on a registration form and I need some advice on how to implement custom name and email validation. Here is the structure of my form: registrationForm = this.formBuilder.group({ name: [''], email: ['' ...

The compatibility issue arises when using Material UI Portal with TypeScript, specifically with the 'children' property types

When rendering a component using Material-UI Portal that includes several Material UI buttons, the following code is used: <Portal container={this.myContainer}> <Button onClick={this.handleClick}>Do something</Button> //other but ...

Is it possible to transform a tuple type into a union?

Is it possible to map a tuple's generic type to a union type? type TupleToUnion<T> = T[keyof T]; // This will include all values in the tuple const value: TupleToUnion<[7, "string"]> = 2; // This assignment should not be permitted since ...

Adjust the range of selection within the Visual Studio Code document

Before running a command in an extension, I need to modify the selection range to include entire lines... const sel = textEditor.selection; const firstLine = textEditor.document.lineAt(sel.start.line); const lastLine = textEditor.document.lineAt(sel.end.l ...

Having trouble with subscribing to a template in Ionic framework

I'm attempting to showcase an image from Firebase storage using the following code: Inside my component : findImg(img) { this.storage.ref('/img/' + img).getDownloadURL().subscribe( result => { console.log(result); ...

The React Table is showing an error due to incompatible property types for 'accessor'

Currently experimenting with react-table in a create-react-app project (version ^7.0.25). Utilizing the example provided in their quick start documentation. However, encountered a type error between the accessor and data columns. Below is the snippet of co ...

Firestore emulator outperforms Firestore in terms of performance

My application is capable of handling a substantial volume of write, read, and update operations (potentially exceeding 10000) under specific conditions. During the development of the app on a local environment, these operations usually complete within a ...

Can a npm package be created using only typescript?

I am working on a project that is specifically tailored for use with TypeScript projects, and I want the code inspection to lead to the actual lines of TypeScript code instead of a definition file. However, I am struggling to set up an npm project to achi ...

What are the TypeScript type definitions for the "package.json" configuration file?

What is the most efficient method for typing the content of the "package.json" file in TypeScript? import { promises as fs } from 'fs'; export function loadManifest(): Promise<any> { const manifestPath = `${PROJECT_DIR}/package.json`; ...

How can a particular route parameter in Vue3 with Typescript be used to retrieve an array of strings?

Encountered a build error: src/views/IndividualProgramView.vue:18:63 - error TS2345: Argument of type 'string | string[]' is not assignable to parameter of type 'string'. Type 'string[]' is not assignable to type 'strin ...

Transforming a mongodb operation into an asynchronous function using await and async syntax

After calling the function to retrieve data from MongoDB, an undefined error occurs. It is suspected that converting the function to an async/await function may resolve this issue. However, there is uncertainty on how to make this conversion without disrup ...

What are the steps for creating a standalone build in nextJS?

Currently, I am undertaking a project in which nextJS was chosen as the client-side tool. However, I am interested in deploying the client as static code on another platform. Upon generating a build, a folder with all the proprietary server elements of ne ...

Retrieving Data from Vuetify Component within vue 3

Currently, I am in the process of creating my own wrapper for Vuetify components to eliminate the need to repeatedly define the same props in each component. For example, I aim to develop a custom TextField with defaultProps while still being able to accep ...

Having difficulty employing jest.mock with a TypeScript class

Following the guidelines outlined in the ES6 Class Mocks page of the Jest documentation, I attempted to test a method on a TypeScript class called Consumer. The Consumer class instantiates a Provider object and invokes methods on it, prompting me to mock t ...

What is the proper way to specify the type of props provided by react-navigation?

My app is built with react native and has a navigation stack set up like this: <Stack.Navigator initialRouteName={NavigationLocations.SIGNUP} ... }}> ... <Stack.Screen nam ...