Easy5 minJavaScript Fundamentals
UpdatedAug 2, 2026
Edit

Array.map and Immutability

CONCEPTS:Immutability

Why This Is Asked

This is a fundamental question to check if a developer understands the difference between mutating and non-mutating array methods. It is especially important in frameworks like React where immutability is required for efficient change detection.

Key Concepts

  • Array.prototype.map() creates a new array with the results of calling a provided function on every element.
  • It does not mutate the original array.
  • The new array has the same length as the original array.
  • If the elements are objects, the new array will contain references to the same objects (shallow copy) unless you explicitly clone them in the callback.

Answers by Technology

+ Add Variant

Expected Answer

Yes, Array.map() always creates a new array.

It iterates over the original array and executes a callback function for each element. The return value of that callback is placed into the same index of a new array, which is then returned after the iteration is complete. The original array remains unchanged.

Why It Matters

In modern JavaScript development (especially with React, Redux, or Vue), immutability is a core principle. You should not modify existing state; instead, you create new versions of it. map() is the standard tool for transforming data without side effects. If you don’t need the returned array, you should probably use forEach() instead.

Example Code

Basic Usage

const numbers = [1, 2, 3];
const doubled = numbers.map(n => n * 2);

console.log(numbers); // [1, 2, 3] (Original unchanged)
console.log(doubled); // [2, 4, 6] (New array)

Shallow Copy Warning

If the array contains objects, map() creates a new array, but the elements in that new array still point to the same objects in memory.

const users = [{ name: 'Alice' }, { name: 'Bob' }];
const newUsers = users.map(u => u);

newUsers[0].name = 'Charlie';
console.log(users[0].name); // 'Charlie' (Mutation!)

Common Mistakes

  • Not returning a value from the callback: If you forget the return statement (or don’t use an implicit return), the new array will be full of undefined.
  • Using map when forEach is appropriate: If you aren’t using the returned array and are just performing side effects (like logging), forEach is more semantically correct and slightly more performant.
  • Mutating elements inside map: Developers sometimes modify the elements of the original array inside the map callback. This defeats the purpose of using a non-mutating method.

Follow-up Questions

  • What is the difference between map() and forEach()? (Answer: map returns a new array, forEach returns undefined).
  • Does filter() also create a new array? (Answer: Yes, it returns a new array containing only elements that pass the predicate).
  • How would you create a deep copy of an array of objects using map()? (Answer: By returning a clone of each object, e.g., arr.map(obj => ({ ...obj }))).

References

Expected Answer

Yes, Array.map() creates a new array. In TypeScript, map is a generic method that allows for type-safe transformations.

The signature looks roughly like this: map<U>(callbackfn: (value: T, index: number, array: T[]) => U): U[]

This means that if you have an array of type T[], and your callback returns a value of type U, map will return a new array of type U[].

Why It Matters

TypeScript’s type inference makes map extremely powerful for data transformation. It ensures that the resulting array’s type is correctly tracked through your application, preventing “property undefined” errors that often occur when manually iterating and pushing to a new array.

Example Code

Type Transformation

interface User {
  id: number;
  name: string;
}

const users: User[] = [
  { id: 1, name: 'Alice' },
  { id: 2, name: 'Bob' }
];

// Automatically inferred as string[]
const names = users.map(user => user.name);

Readonly Arrays

If you are using ReadonlyArray<T>, map is one of the few methods available because it does not mutate the original.

const nums: readonly number[] = [1, 2, 3];
// nums.push(4); // Error: Property 'push' does not exist
const doubled = nums.map(n => n * 2); // OK: returns a new array

Common Mistakes

  • Incorrect Type Casting: Sometimes developers try to cast the result of map instead of letting TypeScript infer it, which can hide bugs if the callback logic changes.
  • Handling Optional Properties: When mapping objects with optional properties, ensure your callback handles undefined values correctly to maintain type safety in the resulting array.

Follow-up Questions

  • How does TypeScript handle the type of the new array? (Answer: It uses generics. The type of the output array is determined by the return type of the callback function).
  • Can map change the type of the elements? (Answer: Yes, this is one of its primary uses—for example, mapping a list of domain objects to a list of UI ViewModels).

References