How to Solve the "TypeError: .reduce is not a function" in JavaScript
The TypeError: x.reduce is not a a function is a common error that occurs when you try to call the Array.prototype.reduce() method on a value that is not an array. This typically happens when you mistakenly believe a variable holds an array, but it actually holds an object, null, undefined, or another non-array type.
This guide will explain the common scenarios that cause this error and show you the correct, modern solutions for both guarding against the error and correctly using reduce on your data.
The Core Problem: .reduce() is an Array-Only Method
The .reduce() method is a function that exists exclusively on the Array.prototype. It is designed to iterate over an array and "reduce" it to a single accumulated value. It does not exist on plain objects, strings, numbers, null, or undefined. When you try to call it on any of these non-array types, JavaScript throws a TypeError.
Example of problem:
// Problem: `myData` is an object, not an array.
let myData = {
a: 1,
b: 2
};
// ⛔️ TypeError: myData.reduce is not a function
let sum = myData.reduce((acc, value) => acc + value, 0);
The key to solving this error is to ensure you are only calling .reduce() on a true array.
Cause 1 (Most Common): The Variable is an Object, Not an Array
This is a very frequent source of the error. You might have a plain object and want to iterate over its values to produce a single result (like a sum), but you try to call .reduce() on the object directly.
Example of problem:
let userScores = {
alice: 10,
bob: 20,
charlie: 30,
};
// ⛔️ TypeError: userScores.reduce is not a function
let totalScore = userScores.reduce((sum, score) => sum + score, 0);
Cause 2: The Variable is undefined or null
This happens when dealing with asynchronous data or optional properties. Your code expects an array, but the variable is undefined because data hasn't loaded yet, or a property doesn't exist.
Example of problem:
function calculateTotal(data) {
// `data.scores` might be undefined if the API response is malformed.
let total = data.scores.reduce((sum, score) => sum + score, 0); // ⛔️ TypeError
return total;
}
calculateTotal({ user: 'Alice' }); // `data.scores` is undefined here.
The Solution: Guarding and Correctly Accessing Data
Guarding with Optional Chaining (?.) (Recommended)
The optional chaining operator (?.) is the most modern and concise way to prevent this error. It will short-circuit the expression if the value on the left is null or undefined, returning undefined instead of throwing an error.
let data = { user: 'Alice' }; // `data.scores` is undefined
// If `data.scores` is nullish, the expression returns `undefined` instead of crashing.
let total = data.scores?.reduce((sum, score) => sum + score, 0);
console.log(total); // Output: undefined
You can combine this with the nullish coalescing operator (??) to provide a safe default value.
// If the reduce operation results in `undefined`, fall back to 0.
let safeTotal = data.scores?.reduce((sum, score) => sum + score, 0) ?? 0;
console.log(safeTotal); // Output: 0
Guarding with a Fallback Array (??)
If you want to ensure your operation always runs on an array, you can provide a fallback empty array using the nullish coalescing operator (??).
let data = { user: 'Alice' };
// If `data.scores` is null or undefined, use `[]` as a fallback.
let total = (data.scores ?? []).reduce((sum, score) => sum + score, 0);
console.log(total); // Output: 0
Reducing an Object's Keys, Values, or Entries
If your data is an object and you want to reduce its contents, you must first convert its keys, values, or entries into an array.
let userScores = {
alice: 10,
bob: 20,
charlie: 30,
};
// To reduce the object's VALUES:
let totalScore = Object.values(userScores).reduce((sum, score) => sum + score, 0);
console.log(totalScore); // Output: 60
// To reduce the object's KEYS:
let allKeys = Object.keys(userScores).reduce((acc, key) => acc + key, '');
console.log(allKeys); // Output: alicebobcharlie
Conclusion
The TypeError: .reduce is not a function is a clear signal that you are attempting to use an array method on a value that is not an array.
To solve it, follow this diagnostic process:
- Is your variable an object? If so, you must first convert its contents to an array using
Object.values(obj),Object.keys(obj), orObject.entries(obj)before you can call.reduce(). - Is your variable
undefinedornull? Guard your code by providing a fallback empty array with the nullish coalescing operator (??):(myVar ?? []).reduce(...). - Is your variable an array-like object (e.g., a
SetorHTMLCollection)? Convert it to a true array first usingArray.from()or the spread syntax (...).