Given an array of objects, I’d like to group it by an arbitrary number of object keys, and sum the values of a second arbitrary number of keys.
For example, given:
const arr = [
{ shape: "square", color: "red", available: 1, ordered: 1 },
{ shape: "square", color: "red", available: 2, ordered: 1 },
{ shape: "circle", color: "blue", available: 0, ordered: 3 },
{ shape: "square", color: "blue", available: 4, ordered: 4 },
];
If I group by both shape
and color
and want the sum of the values of available
and ordered
, the result should be:
[
{ shape: "square", color: "red", available: 3, ordered: 2 },
{ shape: "circle", color: "blue", available: 0, ordered: 3 },
{ shape: "square", color: "blue", available: 4, ordered: 4 },
];
I’ve extensively gone through many similar SO threads [1, from which the example above is based on, 2, 3, 4, 5]. The issue is that none of them:
- Provide a generic, ready-to-use function (they’re based on custom object keys)
- Are based on Typescript and provide a type-safe implementation
- Deal adequately with additional keys in the object (e.g., if
arr
contained another propertysize
not involved in the transformation it shouldn’t contain bogus values)
How can I build a generic, type-safe groupBySum
function that accepts multiple grouping and summing keys?
2
Answers
The following TypeScript function meets all the desired criteria:
The code snippet below uses the JavaScript equivalent to showcase a few examples based on your
arr
:The Typescript implementation is type-safe. For example, if we try to pass an invalid key...
... the compiler will complain:
The returned object is also type-safe. For example, the type of
ans
in......is:
Finally, note that any keys not involved in the transformation are dropped. The example above doesn't contain
color
oravailable
, which couldn't possibly contain meaningful values. This is built in the return type, so TypeScript knows not to expect them.You can do: