skip to Main Content

Im trying to turn this:

[{price: 30, date: 05}, {price: 60, date: 05}, {price: 40, date: 06}, {price: 70, date: 06}  ]

into this:

[{price: 90, date: 05}, {price 110, date: 06}]

Does anyone know how to do this in typescript? I keep getting the following error for trying to type the initial value:

  Types of parameters 'acc' and 'previousValue' are incompatible.

Here’s what I tried:

  const reducedExpenses = expenses.reduce(
    (acc, { date, price }, index) => {
      if (acc[index].date === date) {
        return { ...acc[index], price: (acc[index].price += price) };
      }
      return acc.push({
        date,
        price,
      });
    },
    [{ date: -1, price: 0 }]
  );

2

Answers


  1. Your issue is that Array.prototype.push() returns a number; the new length of the array. You’re using this value as the accumulator.

    What you’re trying to do is most easily achieved by creating a map of keys-to-sums then transforming that map back into an array.

    const expenses = [{price: 30, date: 05}, {price: 60, date: 05}, {price: 40, date: 06}, {price: 70, date: 06}];
    
    const priceSumByDate = expenses.reduce(
      (map, { price, date }) => map.set(date, (map.get(date) ?? 0) + price),
      new Map(), // TS Map<number, number>
    );
    
    const reducedExpenses = [];
    priceSumByDate.forEach((price, date) => {
      reducedExpenses.push({ price, date });
    });
    console.log(reducedExpenses);

    I’ve used a Map here instead of a plain object in order to preserve your (rather odd) octal literal date properties without losing fidelity to string serialisation.

    Login or Signup to reply.
  2. You should always return an array, instead of returning an object in one branch and a number in another.

    To simplify the code, you can start the accumulator as an empty array (giving acc an explicit type) and use .at(-1) to access the previous value.

    const expenses = [{price: 30, date: 5}, {price: 60, date: 5}, {price: 40, date: 6}, {price: 70, date: 6}];
    const reducedExpenses = expenses.reduce((acc: typeof expenses[number][], { date, price }) => {
        const prev = acc.at(-1);
        if (prev && prev.date === date) prev.price += price;
        else acc.push({date, price});
        return acc;
    }, []);
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search