The TC39 Pattern Matching proposal (Stage 2 as of 2025) introduces a match expression to JavaScript that is far more powerful than switch: it supports destructuring, guard clauses, binding, and checks against both value and shape. You can experiment with it today using the @babel/plugin-proposal-pattern-matching Babel plugin.
Problem: JavaScript conditional logic based on data structure — parsing a REST API response that can be a single item or an array, or a WooCommerce cart that may or may not have a coupon — requires nested if/instanceof checks that obscure intent.
Solution: Use the TC39 Pattern Matching proposal (stage 2, available via Babel plugin) — match (value) { when Array: ..., when { type: 'product' }: ... }. Patterns can match on type, shape, and value simultaneously, making discriminated union handling readable and exhaustive.
The examples below show basic value matching, object-shape matching with guards, array pattern matching, and a real-world fetch-result handler that replaces a chain of if/else if blocks.
// ── 1. Basic value matching ──────────────────────────────────────────────
const status = 404;
const message = match (status) {
when (200) { 'OK' }
when (201) { 'Created' }
when (400) { 'Bad Request' }
when (404) { 'Not Found' }
when (500) { 'Server Error' }
else { `Unknown status ${status}` }
};
// ── 2. Object-shape matching ─────────────────────────────────────────────
function describeShape(shape) {
return match (shape) {
when ({ kind: 'circle', radius }) { `Circle r=${radius}` }
when ({ kind: 'rect', w, h }) { `Rect ${w}×${h}` }
when ({ kind: 'triangle', base, h }) { `Triangle b=${base} h=${h}` }
else { 'Unknown shape' }
};
}
// ── 3. Guard clauses ─────────────────────────────────────────────────────
function classify(n) {
return match (n) {
when (x) if (x < 0) { 'negative' }
when (0) { 'zero' }
when (x) if (x < 10) { 'small positive' }
else { 'large positive' }
};
}
// ── 4. Real-world fetch result handler ───────────────────────────────────
async function fetchUser(id) {
const res = await fetch(`/api/users/${id}`);
const body = res.ok ? await res.json() : null;
return match ({ ok: res.ok, status: res.status, body }) {
when ({ ok: true, body: { name, email } }) { `${name} <${email}>` }
when ({ status: 401 }) { throw new Error('Unauthorised') }
when ({ status: 404 }) { null }
when ({ status: s }) if (s >= 500) { throw new Error(`Server error ${s}`) }
else { throw new Error('Unexpected response') }
};
}
NOTE: The pattern-matching proposal syntax is not yet in any stable browser runtime — use it only behind a Babel transform in production; for today's JavaScript use explicit if/else chains or a small helper library like ts-pattern (TypeScript) that provides the same ergonomics.