How to Resolve "TypeError: .map is not a function" Error in JavaScript
The TypeError: x.map is not a function is a common error that occurs when you try to call the Array.prototype.map() 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 iterating over the data you have.
The Core Problem: .map() is an Array-Only Method
The .map() method is a function that exists exclusively on the Array.prototype. It is designed to create a new array by transforming each element of a source array. 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 = {
item1: 'apple',
item2: 'banana'
};
// ⛔️ TypeError: myData.map is not a function
let result = myData.map(item => item.toUpperCase());
The key to solving this error is to ensure you are only calling .map() 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 receive a JSON object from an API where the data is structured as key-value pairs, but you try to treat it like an array.
Example of problem:
let usersById = {
'user-1': { name: 'Alice' },
'user-2': { name: 'Bob' },
};
// ⛔️ TypeError: usersById.map is not a function
let userNames = usersById.map(user => user.name);
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 processData(data) {
// `data.items` might be undefined if the API response is malformed.
let itemNames = data.items.map(item => item.name); // ⛔️ TypeError
return itemNames;
}
processData({ user: 'Alice' }); // `data.items` 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.items` is undefined
// If `data.items` is nullish, the expression returns `undefined` instead of crashing.
let itemNames = data.items?.map(item => item.name);
console.log(itemNames); // Output: undefined
You can combine this with the nullish coalescing operator (??) to provide a safe default value.
// If the map operation results in `undefined`, fall back to an empty array.
let safeItemNames = data.items?.map(item => item.name) ?? [];
console.log(safeItemNames); // Output: []
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.items` is null or undefined, use `[]` as a fallback.
let itemNames = (data.items ?? []).map(item => item.name);
console.log(itemNames); // Output: []
Mapping Over an Object's Keys, Values, or Entries
If your data is an object and you want to iterate over it, you must first convert its keys, values, or entries into an array.
let usersById = {
'user-1': { name: 'Alice', status: 'active' },
'user-2': { name: 'Bob', status: 'inactive' },
};
// To map over the object's VALUES:
let userNames = Object.values(usersById).map(user => user.name);
console.log(userNames); // Output: ['Alice', 'Bob']
// To map over the object's KEYS:
let userIds = Object.keys(usersById).map(key => key.toUpperCase());
console.log(userIds); // Output: ['USER-1', 'USER-2']
// To map over both KEYS and VALUES:
let userEntries = Object.entries(usersById).map(([key, value]) => {
return `${key}: ${value.name}`;
});
console.log(userEntries); // Output: ['user-1: Alice', 'user-2: Bob']
Output:
['Alice', 'Bob']
['USER-1', 'USER-2']
['user-1: Alice', 'user-2: Bob']
Conclusion
The TypeError: .map 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
undefinedornull? If so, use optional chaining (?.) or provide a fallback array (?? []) to guard against the error. Then, investigate why the value isundefinedat its source. - Is your variable an object? If you want to map over its contents, you must first convert them to an array using
Object.keys(),Object.values(), orObject.entries().