HackerReposA FIELD GUIDE TO OPEN SOURCE
ProSponsor the shelf♧ 0
← Back to top all-time
tc39
proposal-record-tuple
HTML2019–2026
tc39 / proposal-record-tuple · Archived

proposal-record-tuple

ECMAScript proposal for the Record and Tuple value types. | Stage 2: it will change!

42Distinct people
47Mentions
0Explicit recommenders
2.5KGitHub stars
REPOSITORY AT A GLANCE

What to know before exploring

What it is

ECMAScript proposal for the Record and Tuple value types. | Stage 2: it will change!

GitHub

Where it is used

No documented product use was verified in the last source check.

What people are saying

No recommendation phrase was found in the indexed comments.

No classified warning is attached to this page. Read the discussions before treating silence as approval.

Also in these discussions

No other repository is repeatedly linked in the same discussions.

This week on Hacker News

Nov 8–Nov 15 UTC · Direct repository links and separately labeled related project stories. Indexed through 11/15/2026, 2:59:58 PM UTC.

No direct repository links were found in the indexed HN discussions over the past seven days. Older discussions are available below.

Mentions over time

HN mentions by year47 dated mentions

Observed mentions: 2019-12-19 16:16:28 UTC to 2026-07-31 07:21:04 UTC.

0369122019-01-01 00:00:00 UTC to 2020-01-01 00:00:00 UTC (exclusive): 1 mentions; 0 submissions, 1 comments20192020-01-01 00:00:00 UTC to 2021-01-01 00:00:00 UTC (exclusive): 9 mentions; 3 submissions, 6 comments2021-01-01 00:00:00 UTC to 2022-01-01 00:00:00 UTC (exclusive): 11 mentions; 0 submissions, 11 comments2022-01-01 00:00:00 UTC to 2023-01-01 00:00:00 UTC (exclusive): 8 mentions; 0 submissions, 8 comments20222023-01-01 00:00:00 UTC to 2024-01-01 00:00:00 UTC (exclusive): 2 mentions; 0 submissions, 2 comments2024-01-01 00:00:00 UTC to 2025-01-01 00:00:00 UTC (exclusive): 10 mentions; 0 submissions, 10 comments2025-01-01 00:00:00 UTC to 2026-01-01 00:00:00 UTC (exclusive): 5 mentions; 2 submissions, 3 comments2026-01-01 00:00:00 UTC to 2027-01-01 00:00:00 UTC (exclusive): 1 mentions; 0 submissions, 1 comments. Incomplete calendar period.2026*

* An incomplete calendar period is marked with an outlined bar. Its count is not directly comparable with a full period.

Counts come from the repository’s dated source evidence. Index cutoff: 2026-11-02 08:16:59 UTC.

View mention counts and date ranges
UTC ranges include their start and exclude their end. Select a period to filter the source evidence.
PeriodStart (UTC)End (exclusive, UTC)MentionsSubmissionsComments
20192019-01-01 00:00:00 UTC2020-01-01 00:00:00 UTC101
20202020-01-01 00:00:00 UTC2021-01-01 00:00:00 UTC936
20212021-01-01 00:00:00 UTC2022-01-01 00:00:00 UTC11011
20222022-01-01 00:00:00 UTC2023-01-01 00:00:00 UTC808
20232023-01-01 00:00:00 UTC2024-01-01 00:00:00 UTC202
20242024-01-01 00:00:00 UTC2025-01-01 00:00:00 UTC10010
20252025-01-01 00:00:00 UTC2026-01-01 00:00:00 UTC523
2026 (partial)2026-01-01 00:00:00 UTC2027-01-01 00:00:00 UTC101

From the project README

An excerpt from the repository, fetched Nov 13, 2026.

Read the project’s introduction
JavaScript Records & Tuples Proposal ImportantThis proposal has been withdrawn #394 Authors: Robin Ricard (Bloomberg) Rick Button (Bloomberg) Nicolò Ribaudo (Babel) Champions: Robin Ricard (Bloomberg) Rick Button (Bloomberg) Advisors Philipp Dunkel (Bloomberg) Dan Ehrenberg (Bloomberg) Maxwell Heiber Stage: Withdrawn Try out Record and Tuple in the playground! Spec Text Tutorial Cookbook Content Overview Examples Syntax Equality The object model Record and Tuple standard library support Rationale Overview This proposal introduces two new deeply immutable data structures to JavaScript: Record, a deeply immutable Object-like structure #{ x: 1, y: 2 } Tuple, a deeply immutable Array-like structure #[1, 2, 3, 4] Records and Tuples can only contain primitives and other Records and Tuples. You could think of Records and Tuples as "compound primitives". By being thoroughly based on primitives, not objects, Records and Tuples are deeply immutable. Records and Tuples support comfortable idioms for construction, manipulation and use, similar to working with objects and Arrays. They are compared deeply by their contents, rather than by their identity. JavaScript engines may perform certain optimizations on construction, manipulation and comparison of Records and Tuples, analogous to the way Strings are often implemented in JS engines. (It should be understood that these optimizations are not guaranteed.) Records and Tuples aim to be usable and understood with external typesystem supersets such as TypeScript or Flow. Prior work on immutable data structures in JavaScript Today, userland libraries implement similar concepts, such as Immutable.js. Also a previous proposal has been attempted but abandoned because of the complexity of the proposal and lack of sufficient use cases. This new proposal is still inspired by this previous proposal but introduces some significant changes: Record and Tuples are now deeply immutable. This property is fundamentally based on the observation that, in large projects, the risk of mixing immutable and mutable data structures grows as the amount of data being stored and passed around grows as well so you'll be more likely to handle large record & tuple structures. This can introduce hard-to-find bugs. As a built-in, deeply immutable data structure, this proposal also offers a few usability advantages compared to userland libraries: Records and Tuples are easily introspectable in a debugger, while library provided immutable types are often hard to inspect as you have to inspect through data structure details. Because they are accessed through typical object and array idioms, no additional branching is needed in order to write a generic library that consumes both immutable and JS objects; with user libraries, method calls may be needed just in the immutable case. We avoid cases where developers may expensively convert between regular JS objects and immutable structures, by making it easier to just always use the immutable ones. Immer is a notable approach to immutable data structures, and prescribes a pattern for manipulation through producers and reducers. However, it is configurable if it generates frozen objects or not. This same pattern can be adapted to the structures defined in this proposal in addition to frozen objects. Deep equality as defined in user libraries can vary significantly, in part due to possible references to mutable objects. By drawing a hard line about only deeply containing primitives, Records and Tuples, and recursing through the entire structure, this proposal defines simple, unified semantics for comparisons. Examples Record const proposal = #{ id: 1234, title: "Record & Tuple proposal", contents: `...`, // tuples are primitive types so you can put them in records: keywords: #["ecma", "tc39", "proposal", "record", "tuple"], }; // Accessing keys like you would with objects! console.log(proposal.title); // Record & Tuple proposal console.log(proposal.keywords[1]); // tc39 // Spread like objects! const proposal2 = #{ ...proposal, title: "Stage 2: Record & Tuple", }; console.log(proposal2.title); // Stage 2: Record & Tuple console.log(proposal2.keywords[1]); // tc39 // Object functions work on Records: console.log(Object.keys(proposal)); // ["contents", "id", "keywords", "title"] Open in playground Functions can handle Records and Objects in generally the same way: const ship1 = #{ x: 1, y: 2 }; // ship2 is an ordinary object: const ship2 = { x: -1, y: 3 }; function move(start, deltaX, deltaY) { // we always return a record after moving return #{ x: start.x + deltaX, y: start.y + deltaY, }; } const ship1Moved = move(ship1, 1, 0); // passing an ordinary object to move() still works: const ship2Moved = move(ship2, 3, -1); console.log(ship1Moved === ship2Moved); // true // ship1 and ship2 have the same coordinates after moving Open in playground See more examples here. Tuple const measures = #[42, 12, 67, "measure error: foo happened"]; // Accessing indices like you would with arrays! console.log(measures[0]); // 42 console.log(measures[3]); // measure error: foo happened // Slice and spread like arrays! const correctedMeasures = #[ ...measures.slice(0, measures.length - 1), -1 ]; console.log(correctedMeasures[0]); // 42 console.log(correctedMeasures[3]); // -1 // or use the .with() shorthand for the same result: const correctedMeasures2 = measures.with(3, -1); console.log(correctedMeasures2[0]); // 42 console.log(correctedMeasures2[3]); // -1 // Tuples support methods similar to Arrays console.log(correctedMeasures2.map(x => x + 1)); // #[43, 13, 68, 0] Open in playground Similarly than with records, we can treat tuples as array-like: const ship1 = #[1, 2]; // ship2 is an array: const ship2 = [-1, 3]; function move(start, deltaX, deltaY) { // we always return a tuple after moving return #[ start[0] + deltaX, start[1] + deltaY, ]; } const ship1Moved = move(ship1, 1, 0); // p
Read the full README on GitHub

What Hacker News says

9 sources
For new code, I think most JS devs have already switched to using the class syntax. Also FP in JS is alive and well if you want to avoid dealing with prototype chains altogether. I think we can all agree the Date API sucks, but life can still be good if you just give in and include a date library. Also, there's some light at the end of the tunnel with Temporal proposal coming along [1]. Object.keys returning string[] is purely a TypeScript design decision, coming from how TypeScript chooses to model object subtyping [2]. type Foo = { a: string } const keysOfFoo = (obj: Foo) => Object.keys(obj) const foo = {a: '', b: 5} keysOfFoo(foo) The fact that this passes type checks is a conscious TS design decision that comes with both advantages and disadvantages. It wouldn't have to be this way; Exact types [3] could potential
Read the rest
ly be used to describe that if the type is exactly Foo, it's safe to assume Object.keys(foo) is (keyof Foo)[]. For first class tuples (and records), there's a stage 2 EcmaScript proposal coming along [4]. There's of course also the readonly [] type in TypeScript if you only need the safety of not accidentally pushing to an "immutable" array. First class language support could have nice additional features though, like strict equality. Anyways, if these are the things you don't like about JS/TS, I don't think AssemblyScript will be the answer for you, as the goals of that language seem to be entirely different from "fixing" old JS cruft. Apart from the i32, i64 stuff I guess. [1] https://github.com/tc39/proposal-temporal [2] https://github.com/Microsoft/TypeScript/pull/12253#issuecomm... [3] https://github.com/microsoft/TypeScript/issues/12936 [4] https://github.com/tc39/proposal-record-tuple
In Show HN: A SQL database implemented purely in TypeScript type annotations
Seems like a lot of options were/are debated: https://github.com/tc39/proposal-record-tuple/issues/10 The benefit to #{}/#[] is that # is not an existing identifier character (other than private fields) in JS, and also isn't an existing binary operator. Proposals to TC39 are constrained that they must as much as possible not "break" existing JS parsing of existing code. That removes a lot of possible characters because they already have valid parses. It also makes it tough to introduce new keywords beyond those ES3/ES5 set in stone as reserved, because they might be identifier names in user applications.
In A first look at records and tuples in JavaScript
This article has a number of problems: it doesn't take into account the primary reason for approaches like VDOM, the history of HTML-in-JS proposals, or the current state-of-the-art in HTML-in-JS. First, the word "update" doesn't appear in the article at all, and efficient and stable updates are the primary reason that client-side template systems are much more complex than their server-side string-concatenation counterparts. Updates are the main reason why you want to treat HTML as structured, because you can't map data changes to DOM changes without some knowledge of the underlying DOM structure. Then there's no mention of E4X (or the lesser-known E4H by Ian Hixie). We've had a proposed syntax, so what went wrong and why not revive it? Again, updates. Creating the initial DOM state isn't that bad. E4X is an incremental improvement over
Read the rest
innerHTML. What matters is updates, and the main difference between JSX and E4X is that E4X created _new_ DOM for every invocation, while JSX is typically used to create a new _description_ of the DOM, which is applied to existing DOM to update it. Any proposal for adding HTML syntax to JS is completely jumping the gun if it doesn't address this point. The syntax matters way less than the semantics on what such markup expressions actually evaluate to and how that result is used to update the DOM. THen, statements like this: > This is rubbish for obvious reasons - composing the strings is bug-prone, no typing/linting etc etc. We then have to turn them into elements with the less than elegant: don't hold up. lit-html[1] (I'm a maintainer) works very much like this and it excels at composition and turning markup into structured data. The complaint is very much in the vein of complaining about embedding a language into strings and saying that just programming with strings. Well, basically every programming language is just strings, with a defined grammar and tools that enforce and extract the structure. This is no different with embeddings, and JS tagged template literals were specifically designed to make embedded languages more useful. lit-html uses the browsers HTML parser to parse the strings, enforcing that they're well-formed. It creates HTML <template> elements that are efficiently cloned for new DOM, and it remembers where the dynamic expressions are in the DOM to efficiently update it on repeated renders. It interpolates data post-clone, so it's robust against XSS. It has a plug-ins for VS Code, TypeScript, eslint, and more, for type-checking, highlighting code-completion, and linting of templates. Which is just to say that string-based templates are a great option that _do_ allow for fast updates, type-checking, composition, and structure, with standard syntax available today. Finally... there are a couple of recent proposals for JavaScript that affect this area. The records and tuples proposal might make it very efficient to describe DOM in object notation. The block parameters proposal[3], though probably defunct now, proposed adding something akin to Kotlin builders, which would have allowed for the attribute/children structure we need for markup. [1]: https://lit-html.polymer-project.org/ [2]: https://github.com/tc39/proposal-record-tuple [3]: https://github.com/samuelgoto/proposal-block-params
In What if we'd had better HTML-in-JS syntax all along?

MAKE YOURSELF AT HOME

A few shortcuts

/
Search the collection
?
Open this guide
Esc
Close dialogs and navigation

Your saved repositories and interests stay in this browser.