How to Sum an Array in TypeScript (Numbers and Objects)

To get the sum of an array in TypeScript, call reduce() with an initial value of 0: it adds every element to a running total and returns a number. Always pass that 0, or an empty array will throw:

const total = sales.reduce((sum, value) => sum + value, 0);

I compiled each example with TypeScript 7.0.2 and Node.js v22.22.2 using strict mode, and the outputs below are copied from those runs.

You’ll see the reduce one-liner, plain loops, summing a property in an array of objects, the string and decimal mistakes that give wrong totals, and which approach is fastest.

Sum an array of numbers with reduce()

reduce() walks the array once. The callback gets the running sum and the current value, and whatever it returns becomes the next sum:

const sales: number[] = [1250.5, 980.25, 1120.75, 640];

const total = sales.reduce((sum, value) => sum + value, 0);
console.log("total:", total);

const empty: number[] = [];
console.log("empty with 0:", empty.reduce((sum, value) => sum + value, 0));
try {
  empty.reduce((sum, value) => sum + value);      // no initial value
} catch (err) {
  console.log("empty without 0:", (err as Error).name, "-", (err as Error).message);
}

Output:

total: 3991.5
empty with 0: 0
empty without 0: TypeError - Reduce of empty array with no initial value
Command Prompt output of TypeScript reduce summing a number array, then a TypeError for an empty array with no initial value
The total prints, an empty array with 0 gives 0, and the same call without 0 throws TypeError.

The initial value also fixes the type: with 0, TypeScript knows the result is a number. For everything else reduce() can do, see my guide to the TypeScript array reduce method.

Sum an array with a for…of loop or forEach

If reduce feels too clever, a loop is perfectly fine and often easier to read for a teammate. Both of these give the same total:

const visits: number[] = [42, 37, 51, 29, 44];

let total = 0;
for (const v of visits) {
  total += v;
}
console.log("for...of:", total);

let total2 = 0;
visits.forEach((v) => (total2 += v));
console.log("forEach: ", total2);

Output:

for...of: 203
forEach:  203

for...of also lets you break early, which forEach can’t. I compare the loop styles in detail in how to loop through an array in TypeScript.

Sum a property in an array of objects

Real data is usually objects, like line items in a cart. Pull out the number you want inside the callback, here price * qty:

interface LineItem {
  name: string;
  price: number;
  qty: number;
}

const cart: LineItem[] = [
  { name: "Coffee beans", price: 14.99, qty: 2 },
  { name: "Mug", price: 9.5, qty: 1 },
  { name: "Filters", price: 4.25, qty: 3 },
];

const subtotal = cart.reduce((sum, item) => sum + item.price * item.qty, 0);
const units = cart.reduce((sum, item) => sum + item.qty, 0);
console.log(`${units} units, subtotal $${subtotal.toFixed(2)}`);

function sumBy<T>(items: readonly T[], pick: (item: T) => number): number {
  return items.reduce((sum, item) => sum + pick(item), 0);
}
console.log("sumBy qty:", sumBy(cart, (i) => i.qty));
console.log("sumBy line totals:", sumBy(cart, (i) => i.price * i.qty).toFixed(2));

Output:

6 units, subtotal $52.23
sumBy qty: 6
sumBy line totals: 52.23
Command Prompt output of TypeScript summing price times quantity across an array of cart objects and a generic sumBy helper
The subtotal in dollars, the unit count, and the same results from a reusable generic sumBy function.

sumBy works for any object type because T is inferred from the array. It accepts readonly arrays too, which is handy with readonly arrays in TypeScript.

Need the biggest value instead of the total? That’s a different reduce; see finding the maximum value in an array of objects.

Why does my TypeScript sum give the wrong answer?

The most common cause is strings. Values from a form, a CSV or query parameters arrive as text, and + joins strings instead of adding them. Strict TypeScript catches it when you seed with 0:

const fromForm: string[] = ["19.99", "5.25", "102"];

const wrong = fromForm.reduce((sum, value) => sum + value, 0);

Output:

sum_strings.ts(3,47): error TS2769: No overload matches this call.
  The last overload gave the following error.
    Type 'string' is not assignable to type 'number'.
Command Prompt output of the TypeScript compiler rejecting reduce on a string array with a number seed: No overload matches this call
The compiler refuses to mix a number seed with string elements.

Convert first, drop anything that isn’t a real number, then add. And watch floating point, which affects any language that uses binary decimals:

const fromForm: string[] = ["19.99", "5.25", "102", "abc"];

const glued = fromForm.reduce((sum, value) => sum + value, "");
console.log("joined strings:", glued);

const total = fromForm
  .map(Number)
  .filter(Number.isFinite)            // drops NaN from "abc"
  .reduce((sum, n) => sum + n, 0);
console.log("numbers:", total);

console.log("0.1 + 0.2 =", 0.1 + 0.2);
const prices = [0.1, 0.2, 19.99];
const cents = prices.reduce((sum, p) => sum + Math.round(p * 100), 0);
console.log("as cents:", cents, "->", `$${(cents / 100).toFixed(2)}`);

Output:

joined strings: 19.995.25102abc
numbers: 127.24
0.1 + 0.2 = 0.30000000000000004
as cents: 2029 -> $20.29

For money, I add whole cents and divide at the end, or round only when displaying with toFixed(2). Getting rid of bad entries first is covered in filtering arrays in TypeScript.

Which way to sum an array is fastest?

Here’s one million numbers summed four ways, each warmed up once before timing so the JIT compiler has done its work:

const data: number[] = Array.from({ length: 1_000_000 }, (_, i) => i % 100);

function time(label: string, fn: () => number): void {
  fn();                                   // warm-up run
  const start = performance.now();
  const result = fn();
  console.log(`${label.padEnd(10)} ${result}  ${(performance.now() - start).toFixed(2)} ms`);
}

time("for", () => { let s = 0; for (let i = 0; i < data.length; i++) s += data[i]; return s; });
time("for...of", () => { let s = 0; for (const v of data) s += v; return s; });
time("reduce", () => data.reduce((s, v) => s + v, 0));
time("forEach", () => { let s = 0; data.forEach((v) => (s += v)); return s; });

Output:

for        49500000  1.45 ms
for...of   49500000  10.04 ms
reduce     49500000  8.38 ms
forEach    49500000  6.33 ms
Command Prompt timing a TypeScript sum over one million numbers with for, for...of, reduce and forEach
All four get the same answer; the classic indexed for loop is quickest on Node.js 22.

Your numbers will differ, but the order usually holds. Unless you’re summing millions of values in a hot path, pick whichever reads best. The same trade-off shows up with the forEach method on TypeScript arrays.

Ways to sum an array in TypeScript compared

ApproachBest forWatch out for
reduce((s, v) => s + v, 0)One-line totalsAlways pass the 0
for...of loopReadable code, early exitRemember to declare let total = 0
reduce on a propertyArrays of objectsStrings from APIs or forms
Generic sumBy()Reusing the logic across typesKeep the picker returning a number

You might also like these array guides:

Frequently asked questions

How do I sum an array of numbers in TypeScript?

Use arr.reduce((sum, value) => sum + value, 0). The 0 is the starting total and makes the result a number.

Why does reduce throw on an empty array?

Without an initial value there’s nothing to start from, so JavaScript throws TypeError: Reduce of empty array with no initial value. Pass 0.

How do I sum a property in an array of objects?

Read the property in the callback: items.reduce((sum, item) => sum + item.price, 0).

Why does my sum look like “19.995.25”?

The values are strings, so + joins them. Convert with Number() first and filter out NaN.

How do I avoid 0.30000000000000004 when adding prices?

Add whole cents as integers and divide by 100 at the end, or round for display with toFixed(2).

Where is Array.prototype.reduce documented?