Released April 1, 2026. This is not a joke. The release date is a coincidence.
ES1995 is the only JS/TS polyfill you'll ever need. The final one. The last one. A coherent set of composable primitives that span the whole stack — with an API surface so smooth, Array.prototype.smooth was redundant and had to be removed. JavaScript: Batteries Included. All of them. Even the weird square one from the smoke detector.
Written in TypeScript with first-class type declarations for a smooth editor experience. Your IDE will thank you. Your coworkers will think you're a wizard. Your code reviewer will weep tears of joy.
Because JavaScript was created in 10 days and it shows. ES1995 is what happens when you give it the 11th day. We've enriched every built-in type — Object, Array, String, Number, Function, Promise, Date, Math, JSON, Error, Symbol, RegExp — with methods that should have been there from the start. No more Math.round(arr.reduce((a, b) => a + b, 0) / arr.length) when you could write arr.average().round(1). Life is too short for ceremony.
"I did JS in 10 days. If I had one more day, ES1995 would be there from the start."
"The Web was done by amateurs. JS is a pile of bricks with limestone on top. In the case of ES1995, a change in perspective is worth negative 80 IQ points."
"If we had ES1995, Rome would be built in a day. Maybe less."
"Discovered that I can speak tweets by pressing the microphone button and it gets it right most of the time — this is amazing and saves a lot of time.
One thing puzzles me.
How did they fit the stenographer inside the phone?"
"TC39 can only see a short distance ahead, but they can see plenty there that needs to be done."
"If JS was like this from the start, humans would dominate the whole galaxy and we would have quantum-resistant Bitcoin with instant transactions running on Neuralink. **nodding**"
God:
"I was looking for a replacement for Perl and JS with ES1995 looks pretty slick!"
Your future self, 3 months from now:
"Why didn't we use this sooner?"
ES1995 enriches every built-in type with composable, predictable methods. The table below is not a wish list. This is what you get. Right now. Today. April 1st.
tapis uniform —tap(fn)always passesthistofn(the whole value), whether called on an Object, Array, or Promise. UseforEachfor element-wise iteration.
| Primitive | Prototype Methods | Static Methods |
|---|---|---|
| Object | pipe, tap, equals, entries, keys, values |
clone, cloneDeep, pick, omit, deepMerge, deepFreeze, defaults, mapKeys, mapValues |
| Array | at, chunk, compact, count, distinct, drop, duplicates, empty, except, first, flattenDeep, frequencies, groupBy, head, intersect, intersperse, last, max, min, average, pairwise, partition, reject, reversed, rotate, scan, shuffle, sortBy, sorted, splitAt, sum, tail, take, toObject, transpose, uniqueBy, union, window, zip |
cartesianProduct, zip |
| String | camelCase, capitalize, chars, count, dedent, escapeHtml, isBlank, isPalindrome, kebabCase, lines, parseQueryString, removeDiacritics, reverse, similarityTo, snakeCase, template, toBytes, toColor, toDate, toDuration, toNumber, truncate, unescapeHtml, words |
uuid |
| Number | absoluteValue, bytes, ceil, clamp, duration, floor, fractionalPart, integerPart, inRange, isEven, isOdd, isPrime, multipleOf, ordinal, pad, round, sign, times, to, toBinary, toFileSize, toHex, toOctal, toRoman |
fibonacci, greatestCommonDivisor, leastCommonMultiple, random, range |
| Function | compose, curry, debounce, delay, flip, memoize, once, partial, retry, throttle |
compose, conditional, constant, fixedPoint, identity, isFunction, noop, pipe, true, false |
| Promise | tap, timeout |
delay, each, filter, map, props, retry, sleep |
| Date | addDays, addHours, addMinutes, addMonths, addSeconds, addYears, age, clone, daysUntil, endOfDay, endOfMonth, format, isFuture, isPast, isSameDay, isToday, isWeekday, isWeekend, relative, startOfDay, startOfMonth |
today, tomorrow, yesterday |
| Math | average, degreesToRadians, factorial, fibonacci, inverseLerp, isPrime, lerp, radiansToDegrees, sum |
|
| JSON | safeParse |
|
| Error | toJSON |
|
| Symbol | documentation |
|
| RegExp | email, hexColor, IPv4, ISO8601, queryString, URL, UUID |
A lightweight, Zod-inspired schema validator — zero dependencies, full chainability:
| Method | Description |
|---|---|
z.string() |
String schema with .min(), .max(), .email(), .url(), .uuid(), .regex(), .nonempty(), .optional() |
z.number() |
Number schema with .min(), .max(), .int(), .positive(), .negative(), .nonnegative(), .optional() |
z.boolean() |
Boolean schema with .optional() |
z.array(schema) |
Array schema with .min(), .max(), .nonempty(), .optional() |
z.object(shape) |
Object schema with .extend(), .pick(), .omit(), .optional() |
z.literal(value) |
Literal value schema |
z.union(...schemas) |
Union schema |
z.enum(...values) |
Enum schema |
All schemas support .parse(value), .safeParse(value), .parseAsync(promiseOrValue), and .safeParseAsync(promiseOrValue).
Globally available deep utility types — no imports needed:
PartialDeep, RequiredDeep, ReadonlyDeep, SetRequired, SetOptional, SetReadonly, Simplify, Merge, ValueOf, Entries, StringKeyOf, Opaque, NonEmptyArray, Writable, WritableDeep
A first-class Color object with perceptually uniform mixing in OKLCH space:
| Method | Description |
|---|---|
Color.from("#ff6347") |
Create from hex string |
Color.rgb(255, 99, 71) |
Create from RGB components |
Color.hsl(9, 100, 64) |
Create from HSL components |
Color.oklch(0.7, 0.15, 30) |
Create from OKLCH (perceptually uniform) |
Color.random() |
Random color |
"#ff6347".toColor() |
String → Color |
.toHex(), .toRGB(), .toHSL(), .toOKLCH() |
Convert between color spaces |
.mix(other, t?) |
Perceptually uniform mixing in OKLCH |
.lighten(n), .darken(n) |
Adjust lightness |
.saturate(n), .desaturate(n) |
Adjust chroma |
.rotate(deg) |
Rotate hue |
.complementary(), .analogous(), .triadic() |
Color harmonies |
.luminance(), .contrastRatio(other) |
Accessibility / WCAG |
ES1995 ships htm + preact as first-class globals — JSX-like syntax via tagged template literals, zero build step:
| Global | Description |
|---|---|
html`<div>…</div>` |
Tagged template → Preact VNodes (via htm) |
render(vnode, container) |
Mount a Preact tree into the DOM |
Components are plain functions. The full ES1995 fluent pipeline feeds directly into html templates:
const App = () => html`<ul>${items.sortBy("name").map(i => html`<li>${i.name}</li>`)}</ul>`
render(html`<${App} />`, document.getElementById("app")!)Data pipeline → rendered Preact UI in 40 lines. No React. No lodash. No moment. No webpack config file longer than your component. Just ES1995 + htm/preact. The speakers are real*. The conference is not**.
import "./es1995"
// 🚀 The galaxy's finest JS speakers
const speakers = [
{ name: "Brendan Eich", talk: "I Did JS in 10 Days (AMA)", planet: "Earth", rating: 9.7, fee: 50000, confirmed: true },
{ name: "God", talk: "Replacing Perl: A Cosmic Journey", planet: "Heaven", rating: 9.9, fee: 0, confirmed: false },
{ name: "Alan Kay", talk: "The Web Is Still a Joke", planet: "Xerox PARC", rating: 8.5, fee: 42000, confirmed: true },
{ name: "Steve Ballmer", talk: "DEVELOPERS DEVELOPERS DEVELOPERS", planet: "Microsoft", rating: 7.2, fee: 99999, confirmed: true },
{ name: "Alan Turing", talk: "What TC39 Can See Ahead", planet: "Bletchley", rating: 9.1, fee: 0, confirmed: false },
{ name: "Sebastian Mackenzie", talk: "Building Rome in < 1 Day", planet: "GitHub", rating: 8.8, fee: 15000, confirmed: true },
{ name: "Joe Armstrong", talk: "Stenographers Inside Phones", planet: "Erlang", rating: 8.0, fee: 12000, confirmed: true },
{ name: "Elon Musk", talk: "Quantum Bitcoin on Neuralink", planet: "Mars", rating: 6.5, fee: 420000, confirmed: false },
]
// 🎪 Build the conference program
const program = speakers
.reject((s) => !s.confirmed) // only confirmed speakers
.sortBy("rating").reversed() // best rated first
.tap((top) => console.log(`🏆 Keynote: ${top.first()!.name}`))
.groupBy("planet") // group by origin
.entries() // Object → Array bridge
.map(([planet, talks]) => ({
planet: planet.capitalize(),
speakers: talks.length,
avgRating: talks.map((t) => t.rating).average().round(1),
totalFees: talks.map((t) => t.fee).sum(),
topSpeaker: talks.sortBy("rating").last()!.name,
badge: Color.hsl(talks.length * 120, 70, 50).toHex(),
topTalk: talks.sortBy("rating").last()!.talk,
}))
.sortBy("avgRating").reversed()
// 🚀 Render it — htm + Preact, no build step needed
const App = () => html`
<h1>🚀 Intergalactic JS Conference</h1>
${program.map((p) => html`
<div style=${{ borderLeft: "4px solid " + p.badge, padding: "0.5rem 1rem", margin: "1rem 0" }}>
<h2>${p.planet}</h2>
<p>🎤 <strong>${p.topSpeaker}</strong> — "${p.topTalk}" · ⭐ ${p.avgRating}</p>
<p>${p.speakers} speakers · 💰 $${p.totalFees.toLocaleString()}</p>
</div>
`)}
`
render(html`<${App} />`, document.getElementById("app")!)What just happened — no React, no lodash, no moment needed:
reject/sortBy/reversed/groupBy— Array pipelines that read like English.entries()— Object→Array bridge for fluent chaining.sum()/.average().round(1)— Number chains, noMath.roundgymnastics.capitalize()— String formatting, built right inColor.hsl(…).toHex()— Color math in one expressionhtml\…`` — Preact components via htm tagged templates, zero JSX transpiler.first()/.last()/.tap()— fluent from start to finish
*Some speakers may be deceased, omnipotent, or fictional. **Unless someone actually organizes it, in which case — dibs on keynote.
"If we had ES1995, Rome would be built in a day. Maybe less." — Sebastian Mackenzie 🚀
Number.range(1, 101)
.map(
Function.conditional([
// 15 === Number.leastCommonMultiple(3, 5)
[(n: number) => n.multipleOf(15), () => "FizzBuzz"],
[(n: number) => n.multipleOf(5), () => "Buzz"],
[(n: number) => n.multipleOf(3), () => "Fizz"],
[Function.true, Function.identity],
]),
)
.join(", ")
.pipe(console.log);const n = -23.47;
const [s, i, f] = [n.sign(), n.integerPart(), n.fractionalPart()];
const m = s * (i + f);
console.assert(n === m);const suits = "♠♥♦♣".split("");
const ranks = [...Number.range(2, 11), ..."JQKA".split("")];
let deck = Array.cartesianProduct(suits, ranks).map((card) => card.join(""));
// Fisher-Yates + random cut
deck = deck.shuffle().rotate(Number.random(0, deck.length));
const players = ["Douglas Crockford", "Marc Andreessen", "John-David Dalton"];
let playersCards;
[playersCards, deck] = deck.splitAt(2 * players.length);
playersCards = Array.zip(...playersCards.chunk(players.length));
const hands = Object.fromEntries(players.zip(playersCards));
let flop, turn, river;
[flop, deck] = deck.drop(1).splitAt(3);
[turn, deck] = deck.drop(1).splitAt(1);
[river, deck] = deck.drop(1).splitAt(1);
const game = {
hands,
community: { flop, turn, river },
};
console.log(game);const mergeSort = (L: number[]): number[] =>
L.length <= 1
? L
: L.splitAt(L.length / 2)
.map(mergeSort)
.pipe((L) => merge(...L));
const merge = Function.conditional([
[(A, B) => A.empty() || B.empty(), (A, B) => A.concat(B)],
[([a], [b]) => a < b, ([a, ...A], B) => [a, ...merge(A, B)]],
[Function.true, (A, B) => merge(B, A)], // ba-dum-ts
]);
Number.range(10).shuffle().pipe(mergeSort).pipe(console.log);Map temperatures to a cold-to-hot gradient using Color.mix (perceptually uniform in OKLCH):
const cold = Color.from("#4285F4"); // cold blue
const hot = Color.from("#EA4335"); // hot red
const temperatures = [18, 22, 35, 15, 28, 31, 20];
const [tMin, tMax] = [temperatures.min(), temperatures.max()];
temperatures
.map((temp) => {
const t = Math.inverseLerp(tMin, tMax, temp);
const color = cold.mix(hot, t); // perceptually uniform!
return { temp: `${temp}°C`, t: t.round(2), color: color.toHex() };
})
.sortBy("temp")
.pipe(console.log);
// { temp: "15°C", t: 0, color: "#4285f4" } ← cold blue
// { temp: "22°C", t: 0.35, color: "#9d6cbb" }
// { temp: "35°C", t: 1, color: "#ea4335" } ← hot redconst students = [
{ name: "Alice", scores: [92, 88, 95, 87] },
{ name: "Bob", scores: [78, 82, 71, 85] },
{ name: "Charlie", scores: [95, 97, 93, 98] },
{ name: "Diana", scores: [65, 72, 68, 74] },
{ name: "Eve", scores: [88, 91, 84, 90] },
];
students
.map((s) => ({
...s,
avg: s.scores.average().round(1),
best: s.scores.max(),
worst: s.scores.min(),
}))
.sortBy("avg")
.reversed()
.map((s, i) => `${(i + 1).ordinal()} ${s.name}: ${s.avg} (${s.worst}–${s.best})`)
.intersperse("---")
.pipe((lines) => lines.join("\n"))
.pipe(console.log);
// 1st Charlie: 95.75 (93–98)
// ---
// 2nd Alice: 90.5 (87–95)
// ---
// 3rd Eve: 88.25 (84–91)
// ---
// 4th Bob: 79 (71–85)
// ---
// 5th Diana: 69.75 (65–74)const text = `To be or not to be that is the question
Whether tis nobler in the mind to suffer
The slings and arrows of outrageous fortune
Or to take arms against a sea of troubles`;
text
.toLowerCase()
.words()
.frequencies()
.pipe(Object.entries)
.sorted(([, a], [, b]) => b - a)
.take(8)
.map(([word, count]) => `${word}: ${"█".repeat(count)} (${count})`)
.pipe((lines) => lines.join("\n"))
.pipe(console.log);
// to: ████ (4)
// the: ██ (2)
// of: ██ (2)
// be: ██ (2)
// ...const milestones = [
{ year: 1995, event: "JavaScript created by Brendan Eich" },
{ year: 1997, event: "ECMAScript 1 standardized" },
{ year: 2009, event: "Node.js released" },
{ year: 2015, event: "ES6/ES2015 – the big leap" },
{ year: 2026, event: "ES1995 becomes the LAST polyfill" },
];
milestones
.map((m) => `${m.year.toRoman()} (${m.year}) – ${m.event}`)
.pipe((lines) => lines.join("\n"))
.pipe(console.log);
// MCMXCV (1995) – JavaScript created by Brendan Eich
// MCMXCVII (1997) – ECMAScript 1 standardized
// MMIX (2009) – Node.js released
// MMXV (2015) – ES6/ES2015 – the big leap
// MMXXVI (2026) – ES1995 becomes the LAST polyfillconst names = [
"Timothée", "Beyoncé", "Penélope", "Renée", "Clémence",
"Zoë", "Chloë", "Øyvind", "Žofia", "Michał", "Clémentine",
];
const searchTerm = "cle";
names
.map((name) => name.removeDiacritics().toLowerCase())
// Sørensen–Dice coefficient: 0.0 – 1.0
.map((safeName) => searchTerm.similarityTo(safeName))
.zip(names)
.sorted(([a], [b]) => b - a)
.take(3)
.pipe(console.log);
// [0.4444, "Clémence"]
// [0.3636, "Clémentine"]
// [0, "Timothée"]"hello world".capitalize(); // "Hello world"
"hello world".camelCase(); // "helloWorld"
"hello world".kebabCase(); // "hello-world"
"hello world".snakeCase(); // "hello_world"
"hello".reverse(); // "olleh"
"hello".chars(); // ["h", "e", "l", "l", "o"]
" ".isBlank(); // true
"racecar".isPalindrome(); // true
"A man a plan a canal Panama".isPalindrome(); // true
"hello hello world".count("hello"); // 2
"42".toNumber() + 1; // 43
"Hello {{name}}, you are {{age}}!".template({ name: "Alice", age: 30 });
// "Hello Alice, you are 30!"
'<script>alert("xss")</script>'.escapeHtml();
// "<script>alert("xss")</script>"(17).isPrime(); // true
(4).isEven(); // true
(7).isOdd(); // true
(1).ordinal(); // "1st"
(23).ordinal(); // "23rd"
(255).toHex(); // "ff"
(255).toBinary(); // "11111111"
(3661000).duration(); // "1h 1m 1s"
(5).to(10); // [5, 6, 7, 8, 9]
(3).times((i) => i * i); // [0, 1, 4]
(1995).toRoman(); // "MCMXCV"
(42).toRoman(); // "XLII"
(2026).toRoman(); // "MMXXVI"
Number.fibonacci(10); // [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]// It is April Fools' Day. The code is real. The date is suspicious.
const now = new Date(2026, 3, 1, 23, 47, 0);
now.format("YYYY-MM-DD HH:mm:ss"); // "2026-04-01 23:47:00"
now.isWeekday(); // true (Wednesday)
now.addDays(7).format("YYYY-MM-DD"); // "2026-04-08"
now.startOfDay(); // 2026-04-01T00:00:00
now.endOfMonth(); // 2026-04-30T23:59:59
// JavaScript's birthday – first public release with Netscape Navigator 2.0
const jsBirthday = new Date(1995, 11, 4); // December 4, 1995
jsBirthday.age(); // 30 (as of 2026-04-01)
jsBirthday.relative(); // "30 years ago"
Date.today(); // start of today
Date.tomorrow(); // start of tomorrow
Date.yesterday(); // start of yesterdayconst double = (x: number) => x * 2;
const addOne = (x: number) => x + 1;
const square = (x: number) => x * x;
// Right-to-left composition
const transform = Function.compose(square, addOne, double);
transform(3); // (3*2+1)² = 49
// Left-to-right pipeline
const pipeline = Function.pipe(double, addOne, square);
pipeline(3); // (3*2+1)² = 49
// Currying
const add = ((a: number, b: number) => a + b).curry();
const add10 = add(10);
add10(5); // 15
// Retry on failure
const fetchData = (() => fetch("/api")).retry(3, 1000);const user = { name: "Alice", age: 30, email: "[email protected]", password: "secret" };
Object.pick(user, ["name", "email"]);
// { name: "Alice", email: "alice@example.com" }
Object.omit(user, ["password"]);
// { name: "Alice", age: 30, email: "alice@example.com" }
Object.deepMerge({ theme: "dark", lang: "en" }, { theme: "light" });
// { theme: "light", lang: "en" }
{ a: 1, b: [2, 3] }.equals({ a: 1, b: [2, 3] }); // trueMath.lerp(0, 100, 0.5); // 50
Math.inverseLerp(0, 100, 75); // 0.75
Math.factorial(10); // 3628800
Math.fibonacci(10); // 55
Math.isPrime(17); // true
Math.degreesToRadians(180); // π
Math.sum(1, 2, 3, 4, 5); // 15
Math.average(1, 2, 3, 4, 5); // 3// Sleep
await Promise.sleep(1000);
// Delay with value
const value = await Promise.delay(100, "hello");
// Tap into promise chain
await fetch("/api")
.tap((response) => console.log("Got:", response.status))
.then((r) => r.json());
// Timeout
await someSlowOperation().timeout(5000);
// Retry
await Promise.retry(() => fetch("/unreliable-api"), { retries: 3, delay: 1000 });JSON.safeParse('{"valid": true}'); // { valid: true }
JSON.safeParse("not json", {}); // {}
JSON.safeParse("broken", { default: true }); // { default: true }RegExp.email.test("[email protected]"); // true
RegExp.UUID.test("550e8400-e29b-41d4-a716-446655440000"); // true
RegExp.hexColor.test("#ff00ff"); // true
RegExp.IPv4.test("192.168.1.1"); // true
RegExp.ISO8601.test("2026-04-01T23:47:00Z"); // true
RegExp.URL.test("https://example.com"); // true"All work and no play makes Jack mass-adopt a polyfill." — ancient proverb
const fetchArticle = (id: string) => {
// get the latest hot shit from Hacker News
};
const fetchArticleOnlyOnce = fetchArticle.memoize();const onResizeWindow = () => {
// recalculate expensive layout
};
const smartOnResizeWindow = onResizeWindow.debounce(150);const onClick = () => {
// http://clickclickclick.click
};
const rateLimitedOnClick = onClick.throttle(1000);const add = (a: number, b: number) => a + b;
const add10 = add.partial(10);const squares = Number.range(10).map((i) => i ** 2);
const squareAtFirst = squares.at(1);
const oddIndices = Number.range(1, 10, 2);
const squaresAtOddIndices = squares.at(oddIndices);const alphabet = "abcdefghijklmnopqrstuvwxyz".chars();
const shift = (text: string, n: number): string =>
text
.chars()
.map((ch) => {
const idx = alphabet.indexOf(ch.toLowerCase());
if (idx === -1) return ch;
const shifted = alphabet[(idx + n + 26) % 26];
return ch === ch.toUpperCase() ? shifted.toUpperCase() : shifted;
})
.join("");
const encrypt = (text: string, key: number) => shift(text, key);
const decrypt = (text: string, key: number) => shift(text, -key);
const message = "Et tu, Brute?";
const encrypted = encrypt(message, 13); // "Rg gh, Oehgr?"
const decrypted = decrypt(encrypted, 13); // "Et tu, Brute?"
// Brute-force all 26 rotations
Number.range(0, 26)
.map((n) => ({ rotation: n, text: shift(encrypted, n) }))
.first((r) => r.text === message)
.pipe(console.log);Parse raw CSV → typed records → aggregate stats in one pipeline:
const csv = `name,department,salary
Alice,Engineering,120000
Bob,Marketing,95000
Charlie,Engineering,135000
Diana,Marketing,105000
Eve,Engineering,128000
Frank,Design,110000
Grace,Design,115000`;
const [headerLine, ...rows] = csv.lines();
const headers = headerLine.split(",");
const employees = rows
.map((row) => row.split(","))
.map((cols) =>
headers.toObject(
(h) => h,
(h, i) => (h === "salary" ? cols[i].toNumber() : cols[i]),
),
);
// Department summary
Object.entries(employees.groupBy("department"))
.map(([dept, members]) => ({
department: dept,
headcount: members.count(),
avgSalary: members.map((m) => m.salary).average().round(0),
topEarner: members.sortBy("salary").reversed().first().name,
}))
.sortBy("avgSalary")
.reversed()
.pipe(console.log);
// Engineering: 3 people, avg $127667, top: Charlie
// Design: 2 people, avg $112500, top: Grace
// Marketing: 2 people, avg $100000, top: Dianaconst now = new Date(2026, 3, 1, 23, 47, 0);
const events = [
{ title: "Standup", offset: 1, hour: 9, min: 0, duration: 15 },
{ title: "Sprint Review", offset: 2, hour: 14, min: 0, duration: 60 },
{ title: "Lunch & Learn", offset: 3, hour: 12, min: 30, duration: 45 },
{ title: "Deploy Window", offset: 4, hour: 16, min: 0, duration: 120 },
{ title: "Retro", offset: 5, hour: 10, min: 0, duration: 90 },
{ title: "Happy Hour", offset: 5, hour: 17, min: 0, duration: 60 },
].map((e) => {
const start = now.startOfDay().addDays(e.offset).addHours(e.hour).addMinutes(e.min);
return {
title: e.title,
day: start.format("YYYY-MM-DD"),
time: `${start.format("HH:mm")}–${start.addMinutes(e.duration).format("HH:mm")}`,
durationStr: (e.duration * 60000).duration(),
};
});
// Group by day → print schedule
Object.entries(events.groupBy("day"))
.sorted(([a], [b]) => a.localeCompare(b))
.map(([day, evts]) =>
`${day}:\n` + evts.sortBy("time").map((e) => ` ${e.time} ${e.title}`).join("\n"),
)
.pipe((lines) => lines.join("\n"))
.pipe(console.log);A single step of Conway's Game of Life using pure array transformations:
type Grid = number[][];
const grid: Grid = [
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 1, 0, 0, 0, 0, 0], // Glider
[0, 0, 0, 1, 0, 0, 0, 0],
[0, 1, 1, 1, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
];
const neighbors = (g: Grid, r: number, c: number): number =>
(-1).to(2)
.flatMap((dr) => (-1).to(2).map((dc) => [dr, dc]))
.reject(([dr, dc]) => dr === 0 && dc === 0)
.map(([dr, dc]) => (g[r + dr] ?? [])[c + dc] ?? 0)
.sum();
const step = (g: Grid): Grid =>
g.map((row, r) =>
row.map((cell, c) => {
const n = neighbors(g, r, c);
return cell === 1
? (n === 2 || n === 3 ? 1 : 0) // survive
: (n === 3 ? 1 : 0); // birth
}),
);
const render = (g: Grid): string =>
g.map((row) => row.map((c) => (c ? "█" : "·")).join(" ")).join("\n");
console.log("Gen 0:\n" + render(grid));
console.log("Gen 1:\n" + render(step(grid)));Functional prime sieve using ES1995 array primitives:
const sieve = (limit: number): number[] => {
const candidates = Number.range(2, limit + 1);
const go = (nums: number[]): number[] => {
if (nums.empty()) return [];
const [prime, ...rest] = nums;
return [prime, ...go(rest.reject((n) => n.multipleOf(prime)))];
};
return go(candidates);
};
const primes = sieve(100);
console.log("Primes:", primes.join(", "));
// Twin primes
primes
.pairwise()
.filter(([a, b]) => b - a === 2)
.map(([a, b]) => `(${a}, ${b})`)
.pipe(console.log); // (3, 5), (5, 7), (11, 13), (17, 19), (29, 31), ...
// Prime gap histogram
primes
.pairwise()
.map(([a, b]) => b - a)
.frequencies()
.pipe(Object.entries)
.sorted(([a], [b]) => a - b)
.map(([gap, count]) => `gap ${gap}: ${"█".repeat(count)} (${count})`)
.pipe(console.log);A personal finance pipeline combining Date, String, Number, and Object:
const transactions = [
{ date: "2026-04-01", category: "food", amount: -45.50, description: "Groceries" },
{ date: "2026-04-01", category: "income", amount: 3200, description: "Salary" },
{ date: "2026-04-02", category: "food", amount: -28.75, description: "Restaurant" },
{ date: "2026-04-03", category: "utilities", amount: -89.00, description: "Electricity" },
{ date: "2026-04-04", category: "income", amount: 450, description: "Freelance" },
// ...
];
// Running balance via scan
transactions
.map((t) => t.amount)
.scan((acc, x) => acc + x, 0)
.zip(transactions)
.map(([bal, t]) => `${t.date} ${t.description.padEnd(15)} → $${bal.toFixed(2)}`)
.pipe(console.log);
// Spending by category
transactions
.reject((t) => t.category === "income")
.groupBy("category")
.pipe(Object.entries)
.map(([cat, txns]) => ({
category: cat,
total: txns.map((t) => t.amount).sum().round(2),
}))
.sortBy("total")
.pipe(console.log);const morseTable: Record<string, string> = {
A: ".-", B: "-...", C: "-.-.", D: "-..", E: ".", F: "..-.",
G: "--.", H: "....", I: "..", J: ".---", K: "-.-", L: ".-..",
M: "--", N: "-.", O: "---", P: ".--.", Q: "--.-", R: ".-.",
S: "...", T: "-", U: "..-", V: "...-", W: ".--", X: "-..-",
Y: "-.--", Z: "--..", " ": "/",
"0": "-----", "1": ".----", "2": "..---", "3": "...--",
"4": "....-", "5": ".....", "6": "-....", "7": "--...",
"8": "---..", "9": "----.",
};
// Build reverse lookup using toObject
const reverseMorse = Object.entries(morseTable)
.toObject(([, code]) => code, ([letter]) => letter);
const encode = (text: string): string =>
text.toUpperCase().chars()
.map((ch) => morseTable[ch] ?? ch)
.join(" ");
const decode = (morse: string): string =>
morse.split(" ").map((code) => reverseMorse[code] ?? code).join("");
encode("Hello World"); // ".... . .-.. .-.. --- / .-- --- .-. .-.. -.."
decode(encode("Hello World")); // "HELLO WORLD"
ES1995 — because the 11th day finally came.
src/es1995.ts — one file, ~2000 lines, zero regrets.
Happy April 1st. The code is real. We checked.