Why Developers Still Write if/else When match Feels Better
When you first discover functional-style pattern matching in JavaScript or TypeScript — something like:
match({
A: (a) => handleA(a),
B: (b) => handleB(b),
})(props)
—it’s hard not to wonder: why are people still writing endless if/else
or switch
statements? The elegance of a declarative match
approach can feel like a breath of fresh air. But in practice, the story is a bit more nuanced. Let’s explore the reasons why if/else
dominates, and where match
truly shines.
The Comfort Zone: Familiarity and Readability
Most developers learned programming with imperative control flow: if/else
, switch
, for
, while
. These constructs are ingrained in almost every mainstream language.
- Onboarding new developers: A junior engineer may find
if/else
easier to follow than an unfamiliarmatch
abstraction. - Code reviews: Teams often prioritize clarity for the average reader over elegance. A
switch
block is predictable; a custommatch
function needs explanation.
Readability is cultural. What looks clean and obvious to a functional programmer can look cryptic to someone without that background.
Tooling, Debugging, and IDE Support
Tooling ecosystems are still better aligned with traditional branching.
- Autocomplete works naturally inside
if
/switch
blocks. - Linters and formatters enforce rules more consistently there.
- Debugging stack traces is often clearer:
if
/else
shows a simple line number, whilematch
may introduce anonymous functions and wrappers.
When you’re working under tight deadlines, better tooling support often trumps elegance.
Flexibility: Complex Conditions
match
works beautifully for discrete cases (enums, tagged unions, prop variants). But what about logic like:
if (x > 10 && y < 5 && user.isActive) {
…
}
Pattern-matching expressions can become awkward or verbose here. In contrast, if/else
is designed for boolean logic without ceremony. This flexibility keeps it relevant.
Performance and Predictability
For small cases, performance differences are negligible. But in tight loops or hot paths:
if/else
andswitch
can be optimized by JS engines into efficient jumps.match
typically adds object lookups and function calls.
Even if the real-world impact is small, some teams default to primitives for predictable performance.
The Weight of Ecosystem Inertia
Open any JavaScript tutorial, read most style guides, or look at Stack Overflow answers: you’ll find if/else
everywhere. Developers stick with what’s “normal,” especially in team settings where unconventional code can raise eyebrows.
This inertia matters. Even if match
is “better,” convincing a team to adopt a different mental model can be an uphill battle.
The Rise of Pattern Matching in JavaScript
It’s worth noting that pattern matching is coming to JavaScript. TC39 (the committee behind JS standards) has a proposal for native syntax like:
match (value) {
when { type: "A", data } => handleA(data),
when { type: "B", data } => handleB(data),
else => handleDefault()
}
When that lands, the argument for if/else
weakens. But until then, most developers either don’t know about libraries like ts-pattern, or avoid them to reduce dependencies.
The Real Killer Feature: Exhaustiveness Checking
Here’s where match
truly wins in TypeScript:
type Shape = { kind: "circle", radius: number }
| { kind: "square", size: number };
match(shape)
.with({ kind: "circle" }, (c) => …)
.with({ kind: "square" }, (s) => …)
.exhaustive(); // ✅ ensures all cases are handled
With if/else
, TypeScript won’t complain if you forget to handle square
. With match
, you get type-checked safety. This prevents entire classes of bugs.
Other Considerations You Might Be Missing
- Team Culture: A “clever”
match
may get rewritten in review if your team values consistency over novelty. - Error Handling: With
if/else
, it’s obvious where theelse
goes. Withmatch
, forgetting a default handler can cause runtime errors. - Learning Curve: Not everyone on the team may understand functional abstractions, leading to accidental misuse.
- Future-Proofing: Betting on proposals or third-party libraries means you must maintain them.
if/else
will never disappear.
So, Which One Should You Use?
- Use
if/else
for quick, ad-hoc conditions or when working in codebases with mixed experience levels. - Use
match
when handling discriminated unions, enums, or structured props, especially in TypeScript where exhaustiveness matters. - Avoid dogma. Both tools have their place, and the best engineers know when to reach for each.
Finally
Once you experience declarative match
, if/else
can feel primitive. But in the real world, factors like familiarity, tooling, flexibility, and inertia keep if/else
alive.
The real shift will happen once JavaScript itself supports pattern matching natively. Until then, you’re likely to see both coexist — with if/else
as the safe, universal option, and match
as the more elegant but niche choice.
Elegance vs. familiarity. Safety vs. simplicity. That’s the balance every developer has to strike.
Comments ()