Hi, I am Sanjeet Tiwari...
Let's talk about

Back to Notes

Deeply Immutable Data Structures

JavaScript Security

Well, a proposal was introduced by the famous TC39 team which pointed to 2 data structures -

  1. Record - A deeply immutable object-like structure.
  2. Tuple - A deeply immutable array-like structure.

What’s “Deeply Immutable” ?

Both the data structures are completely based on primitives, and can only contain primitive data types.

And since they only deal with primitives, they are themselves primitives, more specifically they are called compound primitives.

I know you must be wondering how do they look like. Here is an example -

// This is a record
const record1 = #{
  name: "Sanjeet",
  prof: "Web Dev"
}

// This is a tuple
const tuple1 = #[1, 2, 3, 4]

Syntactically, Records and tuples are just objects and arrays prefixed with a #.

But this # gives them superpowers!

Superpowers

  1. They are compared deeply by their contents.
function generateRecord(first, second) {
  return #{
    text: `${first} ${second}`
  }
}

const record1 = generateRecord("I am amazed by", "Records and Tuples");
const record2 = generateRecord("I am", "amazed by Records and Tuples");

console.log(record1 === record2) // this will return true, as contents of both the records are same.
  1. All operations that can be performed on Objects and Arrays can be applied to Records and Tuples respectively.
const rec = #{
  a: 1,
  b: 2
}

console.log(Object.keys(rec)); // This will work fine

for (let k in rec) {
  // this will work fine too
}

const tup = #[1, 2, 3, 4, 5];
console.log(tup[1]) // it'll print 2
console.log(tup.map(t => t*2)) // it'll print [2, 4, 6, 8, 10]
  1. Since Records and Tuples themselves are primitives, they can exist within each other!.
const rec = #{
  name: "Sanjeet Tiwari",
  tech: #["React", "JavaScript", "TypeScript"],
}
// This will work just fine, as a Tuple is also a primitive
  1. And yes, the most obvious one - they are deeply immutable by default. You won’t be able to do things like -
const rec = #{
  a: 1,
}
rec.a = 3; // This will give an error

const tup = #[1, 2];
tup.push(3); // This will give an error

const instance = new MyClass();
const constContainer = #{
    instance: instance
};
// This will also give an error, as only primitives can stay inside a record or a tuple

const tup2 = #[,] // This will give an error as holes are not allowed here.
// Holes are allowed in a normal array though in JavaScript

Advantages

This is why I feel Records and Tuples are revolutionary -

const clonedObj = JSON.parse(JSON.stringify(objToClone));
// now operations can be performed on clonedObj without worrying about
// its original contents

When can we use them ?

As of December 2024, the Record and Tuple proposal for JavaScript is at Stage 2 in the TC39 process.

This stage indicates that the proposal is under active development but is not yet finalized or implemented in JavaScript engines.

Which means, we all will have to wait a bit more for Records and Tuples to be widely accepted. Meanwhile, there are always polyfills that we can use.

So yeah, go crazy if you want!

Please go through the proposal link as well, as it brilliantly provides more advanced insights on these first-of-their-kind compound primitives, and what future holds for immutability in JavaScript.

Sanjeet's LinkedIn

Records and Tuples

TC39

Last updated on 24-12-2024