Home > Mobile >  Typescript - handling dynamic grouped results in js
Typescript - handling dynamic grouped results in js

Time:04-11

I currently have an endpoint that returns JSON that looks like this:

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"
        },
    
    ]

Imagine this JSON contains a shed ton of data_types of various forms. At the moment, there is output_type **(2)** and input_type **(1)** - but this could be extensive. So, as a result of that to simplify the front end, I'm grouping this.

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

Something like the above in Lodash, it doesn't really matter, but all you need to know is that data type will become a key, and the final JSON I'm trying to type looks like this:

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

    }

The below is an example of how I'd prob going about Typing 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 question, however, is that given that the endpoint can return any data_type at any point, my type here:

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

isn't dynamic in any way, and relies on me the developer defining each key. I'm wondering if there's some magic way with Generic or something to make this more flexible, and if so what that would look like.

edit I think Dictionary<ToolDefinition[]> is the answer, but not 100% sure.

CodePudding user response:

I suggest you should go for Record<string, TagDefinition[]>, you can convert the input data easily but using data_type as the key and then inserting the required fields.

CodePudding user response:

Given a shape for your data:

type Data = {
 name: string;
 id: string;
 data_type: "input_type" | "output_type";
};

This should set you on your way:

type Grouped<T, K extends keyof T> = T[K] extends PropertyKey ? Record<T[K], T[]> : never; 

type GroupedResult = Grouped<Data, "data_type">;// -> { input_type: Data[]; output_type: Data[]; }

And if you want to remove the common key, K from T:

type GroupedOmitKey<T, K extends keyof T> = T[K] extends PropertyKey ? Record<T[K], Pick<T, Exclude<keyof T, K>>[]> : never;

type GroupedOmitKeyResult = GroupedOmitKey<Data, "data_type">; // -> { input_type: Array<{ name: string; id: string; }>; output_type: Array<{ name: string; id: string; }>; }
  • Related