javascriptnode.jstypescript

How to enable Object.groupBy() in TypeScript and Node.js


I am running on Node.js v18.17.1 and TypeScript v5.

I heard about the new JavaScript method Object.groupBy().

const inventory = [
  { name: "asparagus", type: "vegetables", quantity: 5 },
  { name: "bananas", type: "fruit", quantity: 0 },
  { name: "goat", type: "meat", quantity: 23 },
  { name: "cherries", type: "fruit", quantity: 5 },
  { name: "fish", type: "meat", quantity: 22 },
];

const result = Object.groupBy(inventory, ({ type }) => type);
console.log(result)

When I write in my code Object.groupBy(), I get the following TypeScript error:

Property 'groupBy' does not exist on type 'ObjectConstructor'.ts(2339)

I have the following TypeScript configuration:

 "compilerOptions": {
    "target": "es5",
    "lib": ["dom", "dom.iterable", "esnext"],
    // ... etc

How can I enable Object.groupBy() so that I can use it in my code?


Solution

  • Here is the PR to enable it: https://github.com/microsoft/TypeScript/pull/56805. It's in state Open at the moment. Hopefully will be merged soon.

    Before it merged you can use a workaround adding these extension interfaces in your project:

    /// {projectSrcRoot}/groupBy.d.ts
    
    interface ObjectConstructor {
        /**
         * Groups members of an iterable according to the return value of the passed callback.
         * @param items An iterable.
         * @param keySelector A callback which will be invoked for each item in items.
         */
        groupBy<K extends PropertyKey, T>(
            items: Iterable<T>,
            keySelector: (item: T, index: number) => K,
        ): Partial<Record<K, T[]>>;
    }
    
    interface MapConstructor {
        /**
         * Groups members of an iterable according to the return value of the passed callback.
         * @param items An iterable.
         * @param keySelector A callback which will be invoked for each item in items.
         */
        groupBy<K, T>(
            items: Iterable<T>,
            keySelector: (item: T, index: number) => K,
        ): Map<K, T[]>;
    }
    
    const basic = Object.groupBy([0, 2, 8], x => x < 5 ? 'small' : 'large');