How to fix “TypeError: map is not a function” in JavaScript

Updated Oct 23, 2023 ⤳ 5 min read

The JavaScript error “TypeError: object.map is not a function” occurs when you call the map() method on a non-array object.

🎧 Debugging Jam

Calling all coders in need of a rhythm boost! Tune in to our 24/7 Lofi Coding Radio on YouTube, and let's code to the beat – subscribe for the ultimate coding groove!" Let the bug-hunting begin! 🎵💻🚀

24/7 lofi music radio banner, showing a young man working at his computer on a rainy autmn night with hot drink on the desk.

A non-array object in JavaScript can be an object literal, a string, a Map or a Set object.

Let’s see a simple example:


let data = {
    course: 'JavaScript for Beginners', 
    language: 'JavaScript'
}

// This will cause the error
let newData = data.map(item => {
    // do something ...
    return item
})

The above code raises the type error because the calling object isn't an array, it's an object literal.

The map() method in JavaScript only works on arrays

JavaScript map function is a part of the array prototype, meaning you can only call it on JavaScript arrays.

Here's how MDN Web Docs defines it:

Array.prototype.map()

The map() method creates a new array populated with the results of calling a provided function on every element in the calling array.

MDN Web Docs

let data = ['apples', 'bananas', 'oranges', 'grapes']

// This is correct
let newArray = data.map(item => {
// do something here ...
return item
})

Please note the Array.prototype.map() method returns a new array.

How to fix "map is not a function"?

Whenever you encounter a "map is not a function" error, inspect the variable calling map() - You can use console.log(data).


console.log(data)

Before making any change to your code, ensure you're calling map() on the right data because you might be calling map() on an object literal, whereas you need an array inside it!

Here's an example:


// ...

let data = {
    success: true,
    items: [
        {
            course: 'JavaScript for beginners'
        },
        {
            course: 'PHP programming'
        },
        {
            course: 'Learning Python'
        }
    ]
}

console.log(data.items)

In the above code, we have to call the map() method on data.items:


// ...

let newArray = data.items.map(item => {
    // do something here ...
    return item
})

Please note if data contains raw JSON, you need to parse it into a valid JavaScript object literal first:


// ...

data = JSON.parse(data)

Object literals and Array.prototype.map()

If you have an object literal and want to use it with the map() function, you must convert it into an array representation.

There are several ways to do this.

Using Object.keys()Since the map() function only works with arrays, you can create an array from the keys in your object, and call map() on the resulting array. 

Consequently, you can access the original array data using the key in a bracket notationdata[key]:


let data = {
    course: 'JavaScript for beginners',
    language: 'JavaScript',
    creator: 'decodingweb.dev'
}

let dataKeys = Object.keys(data)
// dataKeys: ['course', 'language', 'creator']

let newData = dataKeys.map(key => {
    // Get the data from the original object with the bracket notation
    let item = data[key]
    
    // do something here ...
    return item
})

Using Object.values()Instead of object keys, you can create an array from the object values too:


let data = {
    course: 'JavaScript for beginners',
    language: 'JavaScript',
    creator: 'decodingweb.dev'
}

let dataKeys = Object.values(data)
// dataKeys: ['JavaScript for beginners, 'JavaScript'', 'decodingweb.dev']

let newData = dataKeys.map(itemValue => {
    // do something here ...
    return itemValue
})

Using Object.entries() method: If you need to access the key/value pairs in your map() callback, use Object.entries(). This function creates an array consisting of [key, value] sub-arrays:


let data = {
    course: 'JavaScript for beginners',
    language: 'JavaScript',
    creator: 'decodingweb.dev'
}

let dataKeys = Object.entries(data)
/*
 dataKeys: [
    ['course',   'JavaScript for beginners']
    ['language', 'JavaScript']
    ['creator',  'decodingweb.dev']
]
*/

let newData = dataKeys.map(item => {
    // do something here ...
    
    console.log(item[0]) // key
    console.log(item[1]) // value
    
    return  item
})

Add a length property to objects with integer-keyed properties: If you have an object with numerical keys, you can make it map-ready by giving it a length property.

Let's see an example:


let data = {
    0: 'JavaScript',
    1: 'PHP',
    2: 'Python'
}

// Adding the length property
data['length'] = 3

/* 
The data now looks like this: 
{
    length: 3,
    0: 'JavaScript',
    1: 'PHP',
    2: 'Python'
}

*/

// We call the map directly from the Array prototype passing data as the context (this)
let newData = Array.prototype.map.call(data, item => item)

Since map() is a function, we can invoke it via call(). We pass our object as the context (this) to the call; The second argument is the callback function, which will be passed to the map() method.

How about JavaScript Map objects?

If you're calling the map() method on a Map object, you'll still get the "TypeError: map is not a function" error.

Luckily, Map objects implement keys(), values(), and entries() methods. Using these methods, you can generate arrays based on keys, values, or key/value pairs respectively (just like object literals in the above examples).


const map1 = new Map()

map1.set('a', 1)
map1.set('b', 2)
map1.set('c', 3)

// Since Map.prototype.keys() return a Map Iterator object, we use the spread operator to turn it into an array
let mapKeys = [...map1.keys()] // [1, 2, 3]

let newData = mapKeys.map(key => {
    // Do something here ...
    
    return [key, map1.get(key)]
})

// Create a new Map object with the transformed array
map2 = new Map(newData)


You could also use map1.values() and map1.entries() methods accordingly.

If you're working with a JavaScript Set object, the algorithm is the same.

Adding a check: Array.isArray()

If you want to call the map() method only if the data is an array, you can put your code inside a conditional statement:


let data = ['JavaScript', 'PHP', 'Python']
let newData = []

if (Array.isArray(data)) {
newData = data.map(item => {
         return item 
       })
}

console.log(newData)

As a result, the map() method will only be called if the respective data object is a JavaScript array.

Wrapping up

Alright, I think that does it! Whenever you encounter the "map is not a function" error, first check you're dealing with array elements. If the input isn't an array object, before anything, ensure you're referring to the right variable or property.

Then, depending on your object (object literal, Map, or Set) transform your data into an array, then call its map() method.

Additionally, you can check if the object is an array, and then, call the map() method against it.

I hope you found this quick guide helpful.

Thanks for reading.

Disclaimer: This post may contain affiliate links. I might receive a commission if a purchase is made. However, it doesn’t change the cost you’ll pay.

`