Understanding JavaScript Record & Tuple Proposal: Immutable Value Types and Their Benefits
This article explains the Stage‑1 JavaScript Record & Tuple proposal, showing how the new immutable value types are created with a leading #, how they differ from objects by using value‑based comparison, and why they improve deep equality, sharing, non‑destructive updates, and usage in Maps and Sets.
Dr. Axel Rauschmayer recently wrote about two Stage‑1 JavaScript features—Record and Tuple—proposed to add immutable, value‑based composite primitive types to the language.
JavaScript currently compares primitive values (e.g., strings) by value, but objects and arrays are compared by identity, meaning two distinct objects with the same content are not equal. The proposal introduces # { x: 1, y: 4 } === # { x: 1, y: 4 } // true and # [ 'a', 'b' ] === # [ 'a', 'b' ] // true to enable value comparison for composite structures.
Records are immutable objects compared by value, while Tuples are immutable arrays compared by value. They are created by prefixing an object or array literal with # . For example:
# { x: 1, y: 4 } # [ 'a', 'b' ]Using typeof shows that records have the primitive type 'record' and tuples have 'tuple' :
typeof # { x: 1, y: 4 } // 'record'
typeof # [ 'a', 'b' ] // 'tuple'Records require string keys and values that are themselves primitive (including other records or tuples). Tuples require elements that are primitive values.
Objects can be shallow‑converted to records or tuples with the factory functions Record({x:1, y:4}) and Tuple.from(['a','b']) . These functions throw if any nested value is not a primitive.
Example usage of a record:
const record = # { x: 1, y: 4 };
assert.equal(record.y, 4);
const { x } = record;
assert.equal(x, 1);
assert.ok(# { ...record, x: 3, z: 9 } === # { x: 3, y: 4, z: 9 });Example usage of a tuple:
const tuple = # [ 'a', 'b' ];
assert.equal(tuple[1], 'b');
const [ a ] = tuple;
assert.equal(a, 'a');
assert.ok(tuple.with(0, 'x') === # [ 'x', 'b' ]);
assert.ok(# [ ...tuple, 'c' ] === # [ 'a', 'b', 'c' ]);Immutable composite values bring several advantages: deep equality becomes a built‑in operation ( === ), they can be safely shared without copying, non‑destructive updates are easy, and they work as reliable keys in Map and Set structures.
Deduplication example with Set :
new Set([ #[3,4], #[3,4], #[5,-1], #[5,-1] ]) // => Set { #[3,4], #[5,-1] }Using composite keys in a Map :
const persons = [
# { name: 'Eddie', address: # { street: '1313 Mockingbird Lane', city: 'Mockingbird Heights' } },
# { name: 'Dawn', address: # { street: '1630 Revello Drive', city: 'Sunnydale' } },
// ...
];
const addressToNames = new Map();
for (const person of persons) {
if (!addressToNames.has(person.address)) {
addressToNames.set(person.address, new Set());
}
addressToNames.get(person.address).add(person.name);
}Filtering objects by address using value equality:
const address = # { street: '1630 Revello Drive', city: 'Sunnydale' };
const result = persons.filter(p => p.address === address);Checking whether cached data changed becomes trivial:
let previousData;
function displayData(data) {
if (data === previousData) return;
// render new data
previousData = data;
}
displayData(#[ 'Hello', 'world' ]); // renders
displayData(#[ 'Hello', 'world' ]); // no render because === is trueTesting frameworks can use deepEqual (or the built‑in === ) directly with records and tuples:
function invert(color) {
return # { red: 255 - color.red, green: 255 - color.green, blue: 255 - color.blue };
}
assert.ok(invert(#{ red:255, green:153, blue:51 }) === #{ red:0, green:102, blue:204 });The new syntax has drawbacks: the # character is already used for private fields, and the literal syntax can look dense. Factory functions ( Record() , Tuple() ) and potential future tagged collection literals could improve readability.
When serialized with JSON.stringify , records become plain objects and tuples become arrays. A hypothetical JSON.parseImmutable would restore them as records and tuples.
Future work may explore making class instances immutable and value‑compared, enabling deep, non‑destructive updates of complex data structures.
360 Tech Engineering
Official tech channel of 360, building the most professional technology aggregation platform for the brand.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.