TypeScript

How to Copy Arrays of Objects vs. Arrays of Primitives in TypeScript

3 min. read

When working with arrays in TypeScript, you may need to create copies of arrays, either of primitive values or objects. There are two common approaches for making these copies: using the .map() method and the spread operator (...). Understanding the differences between these methods is crucial, particularly regarding how they handle references for objects versus values for primitives.

Copying Arrays of Primitives

When copying arrays of primitive values, both the .map() method and the spread operator create shallow copies of the array, meaning the new array contains the same primitive values, but is a distinct array in memory.

Using the Spread Operator

const numbers: number[] = [1, 2, 3, 4, 5];
const copyWithSpread = [...numbers];

console.log(copyWithSpread); // [1, 2, 3, 4, 5]

// Modifying the copied array does not affect the original
copyWithSpread[0] = 10;
console.log(copyWithSpread); // [10, 2, 3, 4, 5]
console.log(numbers);        // [1, 2, 3, 4, 5] (remains unchanged)
Copying an array of primitives using the spread operator

Using the .map() Method

const numbers: number[] = [1, 2, 3, 4, 5];
const copyWithMap = numbers.map(num => num);

console.log(copyWithMap); // [1, 2, 3, 4, 5]

// Modifying the copied array does not affect the original
copyWithMap[0] = 10;
console.log(copyWithMap); // [10, 2, 3, 4, 5]
console.log(numbers);     // [1, 2, 3, 4, 5] (remains unchanged)
Copying an array of primitives using the map() function

In both cases, the original array remains unchanged after modifying the copied array, as primitive values are copied by value.

Copying Arrays of Objects

When copying arrays of objects, using the spread operator or the .map() method can create shallow copies of the array. However, the objects themselves are still referenced, meaning changes to the objects in the copied array will affect the original objects.

Using the Spread Operator

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

const items: Item[] = [
  { id: 1, name: 'Item 1' },
  { id: 2, name: 'Item 2' },
  { id: 3, name: 'Item 3' }
];

const copyWithSpread = [...items];

console.log(copyWithSpread);
// [{ id: 1, name: 'Item 1' }, { id: 2, name: 'Item 2' }, { id: 3, name: 'Item 3' }]

// Modifying an object in the copied array affects the original object
copyWithSpread[0].name = 'Updated Item 1';
console.log(copyWithSpread[0].name); // 'Updated Item 1'
console.log(items[0].name);          // 'Updated Item 1' (changed because 'copyWithSpread' holds a reference to the original object)
Copying an array of objects using the spread operator

Using the .map() Method

To create a true deep copy of each object in the array, you need to ensure each object itself is also copied, not just the array structure.

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

const items: Item[] = [
  { id: 1, name: 'Item 1' },
  { id: 2, name: 'Item 2' },
  { id: 3, name: 'Item 3' }
];

const copyWithMap = items.map(item => ({ ...item }));

console.log(copyWithMap);
// [{ id: 1, name: 'Item 1' }, { id: 2, name: 'Item 2' }, { id: 3, name: 'Item 3' }]

// Modifying an object in the copied array does not affect the original object
copyWithMap[0].name = 'Updated Item 1';
console.log(copyWithMap[0].name); // 'Updated Item 1'
console.log(items[0].name);       // 'Item 1' (remains unchanged)
Copying an array of objects using the map() function

In this case, using .map() with an inner spread operator to create a new object ensures that each object is copied, not just the array. This results in a deep copy of the array where changes to the copied objects do not affect the original objects.

Conclusion

When copying arrays of primitive values in TypeScript, both the spread operator and the .map() method creates shallow copies where each element is copied by value. However, when copying arrays of objects, the spread operator alone results in a shallow copy where the objects are referenced, meaning changes to the copied objects affect the originals. To create a true deep copy of an array of objects, you can use the .map() method with the spread operator inside the mapping function. Understanding these distinctions is crucial for managing data immutability and ensuring the integrity of your data structures in TypeScript.

We'd love to hear from you! Reach us via Twitter, Linkedin, or send us a message.

Kim Pham

Senior Front-end Web Developer