Top ECMAScript Proposals Shaping the Future of JavaScript
This article surveys the most noteworthy ECMAScript proposals—from Record & Tuple and the .at() method to Temporal, private methods, top‑level await, import assertions, error cause, decorators, iterator helpers, throw expressions, upsert, observable, do‑expressions, pipeline operator, partial‑application syntax, and await.opts—explaining their purpose, current stage, and providing practical code examples.
Recently, several intriguing ECMAScript proposals have emerged, such as Record & Tuple, throw expressions, and Error Cause, promising a new wave of JavaScript evolution. This article lists the proposals the author finds most worth following, covering new APIs, syntax changes, and their current TC39 stages.
Background
ECMA (European Computer Manufacturers Association) maintains standards like ECMAScript (ECMA‑262). TC39, the technical committee of ECMA, drives the evolution of JavaScript through five stages: strawman (stage 0), proposal (stage 1), draft (stage 2), candidate (stage 3), and finished (stage 4).
Record & Tuple (stage 2)
The proposal-record-tuple adds two immutable data structures—Record (object‑like) and Tuple (array‑like). Their members are compared by value, so identical Records or Tuples are === true.
const proposal = #{
id: 1234,
title: "Record & Tuple proposal",
contents: `...`,
keywords: #["ecma", "tc39", "proposal", "record", "tuple"]
};
const measures = #[42, 12, 67, "measure error: foo happened"];.at() – Relative Indexing (stage 3)
Array.prototype.at()and similar methods for strings and typed arrays allow negative indices to access elements from the end, simplifying code that previously required arr[arr.length‑1] or arr.slice(-N)[0].
const last = arr.at(-1); // same as arr[arr.length‑1]Temporal (stage 3)
The proposal-temporal introduces a global Temporal namespace offering modern date‑time APIs, such as Temporal.Instant, Temporal.PlainDate, Temporal.PlainTime, and Temporal.Duration.
const instant = Temporal.Instant.from('1969-07-20T20:17Z');
const date = Temporal.PlainDate.from({year:2006, month:8, day:24});
const time = Temporal.PlainTime.from({hour:19, minute:39, second:9, millisecond:68, microsecond:346, nanosecond:205});
const duration = Temporal.Duration.from({hours:130, minutes:20});Private Methods (stage 3)
The proposal-private-methods adds true private fields, methods, and accessors to JavaScript classes using the # syntax, independent of TypeScript’s private keyword.
class IncreasingCounter {
#count = 0;
get value() { console.log('Getting the current value!'); return this.#count; }
increment() { this.#count++; }
}Top‑level await (stage 4)
proposal-top-level-awaitallows await to be used directly at the module’s top level without wrapping it in an async function, a feature already supported in Node 14.8+.
const data = await fetch('./data.json');Import Assertions (stage 3)
With proposal-import-assertions, import statements can declare the expected module type, e.g., import json from "./foo.json" assert {type: "json"}, improving safety for JSON and other non‑script modules.
import json from "./foo.json" assert {type: "json"};
import("./foo.json", {assert: {type: "json"}});Error Cause (stage 3)
The proposal-error-cause lets errors carry a cause property, enabling clearer propagation of underlying failures.
await fetch(url).catch(err => {
throw new Error('Download failed', {cause: err});
});Decorators (stage 2)
Decorators, now in their third draft, allow annotation of classes, methods, and fields. They are heavily used by frameworks like Angular, NestJS, and MidwayJS.
Iterator Helpers (stage 2)
proposal-iterator-helpersadds utility methods to iterators, similar to Python’s itertools, enabling operations like filter directly on generator objects.
function* naturals() { let i = 0; while (true) { yield i++; } }
const evens = naturals().filter(n => n % 2 === 0);
for (const even of evens) console.log(even, 'is an even number');Throw Expressions (stage 2)
With proposal-throw-expressions, throw can appear inside expressions, e.g.,
const encoder = encoding === "utf8" ? new UTF8Encoder() : throw new Error("Unsupported encoding"), supporting expression‑oriented programming.
function getEncoder(encoding) {
const encoder = encoding === "utf8" ? new UTF8Encoder()
: encoding === "utf16le" ? new UTF16Encoder(false)
: encoding === "utf16be" ? new UTF16Encoder(true)
: throw new Error("Unsupported encoding");
}Upsert (Map.prototype.emplace) (stage 2)
The proposal-upsert adds an emplace method to Map, inserting a new entry or updating an existing one in a single call.
myMap.emplace(key, value);Observable (stage 1)
proposal-observablebrings RxJS‑style Observables to the language, introducing Observable, Observer, and related operators with lazy data emission.
function listen(element, eventName) {
return new Observable(observer => {
const handler = event => observer.next(event);
element.addEventListener(eventName, handler, true);
return () => element.removeEventListener(eventName, handler, true);
});
}Do Expressions (stage 1)
Similar to throw expressions, do { … } allows a block to produce a value, enabling more concise functional patterns.
let x = do { let tmp = f(); tmp * tmp + 1 };
let y = do { if (foo()) f(); else if (bar()) g(); else h() };Pipeline Operator (stage 1)
The |> operator improves readability of chained function calls, turning exclaim(capitalize(doubleSay("hello"))) into a left‑to‑right pipeline.
let result = "hello"
|> doubleSay
|> capitalize
|> exclaim;Partial Application Syntax (stage 1)
This proposal introduces a concise syntax for currying functions, using ? as a placeholder for arguments to be supplied later.
const addOne = add(1, ?);
const addTen = add(?, 10);
let newScore = person.score
|> double
|> add(7, ?)
|> boundScore(0, 100, ?);await.opts (stage 1)
proposal-await.optsadds await.all, await.race, await.allSettled, and await.any as syntactic sugar for the corresponding Promise methods.
// before
await Promise.all(users.map(async u => fetchProfile(u.id))
// after
await.all users.map(async u => fetchProfile(u.id))These proposals illustrate the ongoing transformation of JavaScript, offering developers more expressive, safer, and performant language features. For a complete list of proposals at various stages, visit the TC39 proposals tracker.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
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.
