array.groupBy in TypeScript

you could add the function to the array prototype in your app (note some don't recomend this: Why is extending native objects a bad practice?):

Array.prototype.groupBy = function(/* params here */) { 
   let array = this; 
   let result;
   /* do more stuff here*/
   return result;
}; 

Then create an interface in typescript like this:

.d.ts version:

    interface Array<T>
    {
        groupBy<T>(func:(x:T) => string): Group<T>[]
    }

OR in a normal ts file:

declare global {
   interface Array<T>
   {
      groupBy<T>(func:(x:T) => string): Group<T>[]
   }
}

Then you can use:

 props.tags.groupBy((t)=>t.category_name)
     .map((group)=>{
                    [...]
                })

You can use the following code to group stuff using Typescript.

const groupBy = <T, K extends keyof any>(list: T[], getKey: (item: T) => K) =>
  list.reduce((previous, currentItem) => {
    const group = getKey(currentItem);
    if (!previous[group]) previous[group] = [];
    previous[group].push(currentItem);
    return previous;
  }, {} as Record<K, T[]>);


// A little bit simplified version
const groupBy = <T, K extends keyof any>(arr: T[], key: (i: T) => K) =>
  arr.reduce((groups, item) => {
    (groups[key(item)] ||= []).push(item);
    return groups;
  }, {} as Record<K, T[]>);

So, if you have the following structure and array:

type Person = {
  name: string;
  age: number;
};

const people: Person[] = [
  {
    name: "Kevin R",
    age: 25,
  },
  {
    name: "Susan S",
    age: 18,
  },
  {
    name: "Julia J",
    age: 18,
  },
  {
    name: "Sarah C",
    age: 25,
  },
];

You can invoke it like:

const results = groupBy(people, i => i.name);

Which in this case, will give you an object with string keys, and Person[] values.

There are a few key concepts here:

1- You can use function to get the key, this way you can use TS infer capabilities to avoid having to type the generic every time you use the function.

2- By using the K extends keyof any type constraint, you're telling TS that the key being used needs to be something that can be a key string | number | symbol, that way you can use the getKey function to convert Date objects into strings for example.

3- Finally, you will be getting an object with keys of the type of the key, and values of the of the array type.