Skip to content

Instantly share code, notes, and snippets.

@jherr
Last active April 12, 2024 06:52
Show Gist options
  • Star 89 You must be signed in to star a gist
  • Fork 13 You must be signed in to fork a gist
  • Save jherr/0f40e9dc60836a1a36c237e094401c93 to your computer and use it in GitHub Desktop.
Save jherr/0f40e9dc60836a1a36c237e094401c93 to your computer and use it in GitHub Desktop.

Frameworks like React require that when you change the contents of an array or object you change its reference. Or push another way that you don't change arrays but instead create new arrays with updated values (i.e. immutability).

There are older array methods that are incompatible with immutability because they alter the array in place and don't change the array reference. These are mutable (or destructive) methods.

Shown below are replacements for the array destructive methods (e.g. push, pop, splice, sort, etc.) that will create new array references with the updated data.

Solutions are provided using the spread operator and also the newer "change array by copy" methods (toSpliced, toSorted, toReversed and with).

Setting Value At Index

Destructive version:

const myArray = [1, 3, 2];
myArray[1] = 10; // [1, 10, 2]

Non-destructive versions:

const myArray = [1, 3, 2];
const newArray = [...myArray];
newArray[1] = 10;

Or:

const myArray = [1, 3, 2];
const newArray = [
  ...myArray.slice(0, 1),
  10,
  ...myArray.slice(2, myArray.length)
];

Or (if you have access to with):

const myArray = [1, 3, 2];
const newArray = myArray.with(1, 10);

Push

Destructive version:

const myArray = [1, 3, 2];
myArray.push(5); // [1, 3, 2, 5]

Non-destructive versions:

const myArray = [1, 3, 2];
const newArray = [...myArray, 5];

Or (if you have access to toSpliced):

const myArray = [1, 3, 2];
const newArray = myArray.toSpliced(myArray.length, 0, 5);

Pop

Destructive version:

const myArray = [1, 3, 2];
const poppedValue = myArray.pop(); // [1, 3]

Non-destructive versions:

const myArray = [1, 3, 2];
const poppedValue = myArray[myArray.length - 1];
const newArray = myArray.slice(0, myArray.length - 1);

Or (if you have access to toSpliced):

const myArray = [1, 3, 2];
const poppedValue = myArray[myArray.length - 1];
const newArray = myArray.toSpliced(myArray.length - 1, 1);

Shift

Destructive version:

const myArray = [1, 3, 2];
const shiftedValue = myArray.shift(); // [3, 2]

Non-destructive version:

const myArray = [1, 3, 2];
const [shiftedValue, ...newArray] = myArray;

Unshift

Destructive version:

const myArray = [1, 3, 2];
myArray.unshift(6); // [6, 1, 3, 2]

Non-destructive versions:

const myArray = [1, 3, 2];
const newArray = [6, ...myArray];

Or (if you have access to toSpliced):

const myArray = [1, 3, 2];
const newArray = myArray.toSpliced(0, 0, 6);

Splice

Destructive version:

const myArray = [1, 3, 2];
myArray.splice(1, 1, 4, 5, 6); // [1, 4, 5, 6, 2]

Non-destructive versions:

const myArray = [1, 3, 2];
const newArray = [
  ...myArray.slice(0, 1),
  4, 5, 6,
  ...myArray.slice(2, myArray.length)
];

Or (if you have access to toSpliced):

const myArray = [1, 3, 2];
const newArray = myArray.toSpliced(1, 1, 4, 5, 6);

Reverse

Destructive version:

const myArray = [1, 3, 2];
myArray.reverse(); // [2, 3, 1]

Non-destructive versions:

const myArray = [1, 3, 2];
const newArray = [...myArray].reverse();

Or (if you have access to toReversed):

const myArray = [1, 3, 2];
const newArray = myArray.toReversed();

Sort

Destructive version:

const myArray = [1, 3, 2];
myArray.sort(); // [1, 2, 3]

Non-destructive versions:

const myArray = [1, 3, 2];
const newArray = [...myArray].sort();

Or (if you have access to toSorted):

const myArray = [1, 3, 2];
const newArray = myArray.toSorted();
@Kumawatlalit912
Copy link

...spread is a life savior

@antpowell
Copy link

@jherr Thanks so much! You said you would share and you did, love all your work!

@jherr
Copy link
Author

jherr commented May 5, 2023

I'm a man of my word. :)

@abdulrahman-newsreels
Copy link

abdulrahman-newsreels commented May 9, 2023

@jherr What if the array has reference values(objects)? Do we need to use any deep cloning methods to avoid mutating the same variable?

@jherr
Copy link
Author

jherr commented May 9, 2023 via email

@abdulrahman-newsreels
Copy link

@jherr Thank you so much!! Appreciate you & your work a lot! :)

@Olalekan101
Copy link

Thank you very much

@alveshelio
Copy link

alveshelio commented Jun 2, 2023

Hi @jherr,

Thank you very much for these precious nuggets 😄
These methods are in state 4, are they already available in Typescript? I was trying to use . toSorted but I'm getting an error toSorted is not a function

I was looking into my tsconfig file and I have "lib": ["DOM", "DOM.Iterable", "ESNext"], in my compilerOptions so I should be good no?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment