What are Tuples and Records in JavaScript?
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);
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.
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 = #[];
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 #['π³', 'π
', 'π₯']
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);
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));
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
};
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(#['π', 'π
', 'π₯']);
And since they are new data types, you would get βrecordβ back when using the typeof
operator:
typeof #{ ... } // returns "record"
typeof #[ ... ] // returns "tuple"
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;
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!
Rocket Launch Your Career
Speed up your learning progress with our mentorship program. Join as a mentee to unlock the full potential of Webtips and get a personalized learning experience by experts to master the following frontend technologies: