What are Tuples and Records in JavaScript?

What are Tuples and Records in JavaScript?

Introduction to new immutable data types in JavaScript
Ferenc Almasi β€’ πŸ”„ 2021 September 18 β€’ πŸ“– 4 min read

Immutability is a common term that often pops up when we talk about functional programming. This is because it is one of its core principles. When we talk about immutable objects, we simply mean that once a variable has been declared, its value cannot be changed later on. For example:

const presents = ['🎁', 'πŸ“¦', 'πŸŽ€', 'πŸ’', 'πŸŽ„'];

// --- Mutable solution ---

// we get back 🎁
// and presents will be equal to ['πŸ“¦', 'πŸŽ€', 'πŸ’', 'πŸŽ„'];
presents.shift();

// --- Immutable solution ---

// newPresents will be equal to πŸ“¦ πŸŽ€ πŸ’ πŸŽ„
// and presents will be still equal to ['🎁', 'πŸ“¦', 'πŸŽ€', 'πŸ’', 'πŸŽ„'];
const newPresents = presents.slice(1);
immutability.js
Copied to clipboard!

The first solution mutates the array, while the second creates a new one and leaves the original intact. In JavaScript, we don’t have real immutable objects, so we either need workarounds to implement safety nets, or worse, we have to trust people that they won’t change the values.

Now there is a new ECMAScript proposal β€” currently at stage 2, so implementation can change β€” that would introduce two new immutable data types: Tuples and Records.

Looking to improve your skills? Check out our interactive course to master JavaScript from start to finish.
Master JavaScript

Tuples

Both tuples and records have the same syntax. They can be defined by using a # prefix in front of objects and arrays, like so:

// This is a normal array
const arr = [];

// This is a tuple
const tuple = #[];
tuple.js
Copied to clipboard!

When working with tuples, there are some rules you need to be aware of:

  • There cannot be holes in an array, eg.: [1, ,2] is disallowed
  • They can only contain primitives or other tuples and records
  • Supports instance methods similar to Arrays, but with a few changes

For example, operations that mutate the array are replaced with new operations that instead, return a new array. Therefore, eg.: there’s no push, instead you can use pushed that returns a new tuple with the pushed value, or with to change a value at a given index:

const tuple = #['πŸ„', 'πŸ…', 'πŸ₯•'];

// Both returns a new tuple
tuple.pushed('πŸ₯’');  // returns #['πŸ„', 'πŸ…', 'πŸ₯•', 'πŸ₯’'];
tuple.with(0, '🌳'); // returns #['🌳', 'πŸ…', 'πŸ₯•']
tuple.js
Copied to clipboard!

You can also create tuples from existing arrays using Tuple.from():

Tuple.from(['πŸ„', 'πŸ…', 'πŸ₯•']);

// Likewise, you can turn a tuple into an ordinary array:
Array.from(tuple);
tuple.js
Copied to clipboard!

And of course, they are immutable and will throw an error if you try to change their value or use non-primitives:

const tuples = #['πŸ„', 'πŸ…', 'πŸ₯•'];

// TypeError: Callback to Tuple.prototype.map may only return primitives, Records or Tuples
tuples.map(tuple => new Button(tuple));
tuple.js
Copied to clipboard!

Records

Just like tuples, records are also denoted by a hash:

// This is a regular object
const obj = { ... };

// This is a record
const record = #{
    tuple: #['πŸ„', 'πŸ…', 'πŸ₯•'] // Records can also contain tuples
};
record.js
Copied to clipboard!

When working with records, you also need to keep in mind some rules:

  • You cannot use the __proto__ identifier in records
  • Methods are also disallowed. Just like tuples, they can only contain primitives.

To create a new record, you also have the option to use Record, or Record.fromEntries when working with tuples:

const record = Record({
    mushroom: 'πŸ„',
    tomato: 'πŸ…',
    carrot: 'πŸ₯•'
});

// Or
const record = Record.fromEntries(#['πŸ„', 'πŸ…', 'πŸ₯•']);
record.js
Copied to clipboard!

And since they are new data types, you would get β€œrecord” back when using the typeof operator:

typeof #{ ... } // returns "record"
typeof #[ ... ] // returns "tuple"
types.js
Copied to clipboard!
Looking to improve your skills? Check out our interactive course to master JavaScript from start to finish.
Master JavaScript

Conclusion

Other than the mentioned examples above, you can use both records and tuples in functions or loops just as you normally would with regular objects.

If you want immutability right now, the easiest way is to use Immutable-js. You can also achieve partial immutability with Object.freeze, however, it only freezes immediate children. Therefore, you can still change deeply nested properties:

const obj = Object.freeze({
    a: 1,
    b: {
        c: 2
    }
});

// βœ… Won't work
obj.a = 10;

// ❌ Will be changed to 20
obj.b.c = 20;
freeze.js
Copied to clipboard!

And of course, you can also use it with Babel with the plugin-syntax-record-and-tuple plugin.

Have you already worked with Tuples and Records? Let us know your thoughts about them in the comments below! Thank you for reading through, happy coding!

Did you find this page helpful?
πŸ“š More Webtips
Frontend Course Dashboard
Master the Art of Frontend
  • check Unlimited access to hundred of tutorials
  • check Access to exclusive interactive lessons
  • check Remove ads to learn without distractions
Become a Pro

Recommended