How Error Cause, Temporal, and Array.findLast Proposals Will Transform JavaScript
The article reviews recent TC39 proposal updates—including Error Cause reaching Stage 3, the Temporal API replacing the flawed Date object, the new Array.findLast methods, and Module Fragments—explaining their motivations, design details, code examples, and how they aim to improve JavaScript development across environments.
Due to the pandemic, TC39 meetings have shifted to a fully online format, reducing the length of each meeting while increasing frequency to mitigate time‑zone challenges. Consequently, the agenda this year is shorter, with fewer progressing proposals.
Error Cause Proposal
The Alibaba‑led proposal "Error Cause" has advanced to Stage 3 and will be implemented in JavaScript engines, with experimental releases in browsers and Node.js.
Stage 2 → Stage 3
Write a complete standard text of the proposal and obtain review and signatures from designated TC39 members.
ECMAScript editors sign off on the proposal.
Proposal link: https://github.com/tc39/proposal-error-cause
The proposal adds an optional options parameter to the Error constructor, allowing a cause property that can hold any JavaScript value (e.g., undefined or a string). This mirrors similar features in C#, Java, and Python, and is already widely used in libraries such as verror and @netflix/nerror. With this addition, developer tools like Chrome DevTools can automatically display the cause value, improving error handling.
try {
return await fetch('//unintelligible-url-a') // throws a low‑level error
.catch(err => {
throw new Error('Download raw resource failed', { cause: err }); // wrap with cause
});
} catch (err) {
console.log(err);
console.log('Caused by', err.cause);
// Error: Download raw resource failed
// Caused by TypeError: Failed to fetch
}Temporal Proposal
The legacy Date API suffers from numerous issues: limited time‑zone support, unreliable string parsing, mutable objects, unpredictable daylight‑saving behavior, impractical calculation API, and lack of non‑Gregorian calendars. Temporal introduces a new global namespace with modern date‑time types to address these problems.
Proposal link: https://github.com/tc39/proposal-temporal
Key design principles of Temporal include:
Easy‑to‑use date and time calculation APIs.
Native time‑zone support, including daylight‑saving handling.
Immutable date‑time objects.
Strict date‑string parsing.
Support for multiple calendars (Gregorian, lunar, Islamic, etc.).
Temporal provides various types (e.g., PlainYearMonth, PlainMonthDay) that enable precise representation of partial dates and avoid zero‑fill pitfalls.
All Temporal types have string representations for storage and transmission, and extensions to ISO‑8601/RFC‑3339 are being standardized.
Common use‑case comparisons:
Date value calculation
With Date, developers must manually read, compute, and set values, leading to errors in leap‑year and month calculations.
const now = new Date('2020-02-29T12:00:00.000Z');
now.setFullYear(now.getFullYear() + 1);
// ❌ Result: 2021-03-01T12:00:00.000Z (incorrect)
// ✅ Expected: 2021-02-28T12:00:00.000ZTemporal provides built‑in arithmetic:
const now = Temporal.PlainDateTime.from('2020-02-29T12:00:00.000Z');
const after = now.add({ years: 1 });
// ✅ after = 2021-02-28T12:00:00.000ZTime‑string parsing
new Date('2019-02-29T12:00:00.000Z')silently corrects invalid dates, whereas Temporal throws a RangeError, forcing developers to handle the error explicitly.
Temporal.PlainDateTime.from('2019-02-29T12:00:00.000Z');
// ✅ throws RangeErrorLeap‑year calculation
Temporal’s Calendar object correctly determines leap years across calendars.
const calendar = Temporal.Calendar.from('iso8601');
const isLeap = year => calendar.inLeapYear(Temporal.PlainYearMonth.from({ year, month: 2 }));
isLeap(1900); // falseArray.findLast Proposal
The proposal introduces Array.prototype.findLast and Array.prototype.findLastIndex, which search from the end of an array, analogous to Array.prototype.find but reversed.
Proposal link: https://github.com/tc39/proposal-array-find-from-last
const array = [{value:1},{value:2},{value:3},{value:4}];
array.findLast(n => n.value % 2 === 1); // => {value:3}
array.findLastIndex(n => n.value % 2 === 1); // => 2
array.findLastIndex(n => n.value === 42); // => -1Module Fragments Proposal
This proposal allows a single JavaScript file to contain multiple named modules, improving performance when bundlers split code while preserving clear module boundaries.
Proposal link: https://github.com/littledan/proposal-module-fragments
// filename: app.js
module "#count" {
let i = 0;
export function count() { i++; return i; }
}
module "#uppercase" {
export function uppercase(string) { return string.toUpperCase(); }
}
import { count } from "#count";
import { uppercase } from "#uppercase";
console.log(count()); // 1
console.log(uppercase("daniel")); // "DANIEL"Compared with the earlier "Module Blocks" concept, Module Fragments have named modules that can be statically imported, while Module Blocks are anonymous and only usable via dynamic import() or workers.
Conclusion
The JavaScript Chinese Interest Group (JSCIG), led by He Shijun and supported by Alibaba’s front‑end standards team, invites developers to discuss ECMAScript topics on GitHub: https://github.com/JSCIG/es-discuss/discussions.
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.
