By the end of this tutorial, you’ll turn long if/else chains into reusable functions with Lodash’s _.cond() and predicate–handler pairs.
01
Core Syntax
Build _.cond([[pred, fn], ...]) tables of rules.
02
First Match Wins
Lodash stops at the first truthy predicate.
03
Default Branch
End with [_.stubTrue, handler] as catch-all.
04
Shared Args
Predicates and handlers receive the same call arguments.
05
Real Rules
Map scores, temperatures, and HTTP status codes.
06
vs switch
Know when a plain if/else or switch is clearer.
Fundamentals
What Is _.cond()?
_.cond() is a Lodash util helper that builds a conditional function from an array of [predicate, handler] pairs. Think of it as a functional if/else ladder: each predicate tests the incoming arguments; the first one that returns a truthy value runs its paired handler, and that handler’s return value is what _.cond() gives back.
💡
Beginner tip
Picture a row of doors. Lodash walks left to right; the first door whose lock (predicate) opens lets you into the room (handler) behind it. Put specific doors before general ones, and leave a final _.stubTrue door as the default fallback.
This pattern keeps branching logic in one declarative table instead of nested if statements—useful for categorizers, routers, and validators you want to pass around as first-class functions.
Foundation
📝 Syntax
Pass an array of two-element pairs—predicate first, handler second:
javascript
_.cond(pairs)
Syntax Rules
pairs — array of [predicate, handler] tuples.
predicate — function returning truthy/falsy; receives the same args as the cond function.
handler — runs when its predicate matches; receives the same args.
Order — first matching pair wins; later pairs are skipped.
No match — returns undefined unless a _.stubTrue default pair exists.
javascript
import cond from "lodash/cond";
import stubTrue from "lodash/stubTrue";
const getSizeCategory = cond([
[(value) => value < 10, () => "Small"],
[(value) => value < 20, () => "Medium"],
[(value) => value < 30, () => "Large"],
[stubTrue, () => "Huge"]
]);
console.log(getSizeCategory(5)); // "Small"
console.log(getSizeCategory(35)); // "Huge"
Cheat Sheet
⚡ Quick Reference
Task
Code pattern
Result
Create cond fn
const fn = _.cond(pairs)
Returns conditional function
Default branch
[_.stubTrue, handler]
Always matches last
Range check
[(n) => n < 0, () => "neg"]
Predicate on first arg
Type guard
[_.isString, (s) => s.trim()]
Handler uses same arg
No match
_.cond([[() => false, fn]])()
undefined
Native alternative
if / else if / else
Imperative equivalent
Returns
Function
New cond function
Evaluation
First match
Short-circuit order
Default
_.stubTrue
Catch-all predicate
Category
Util
Functional helper
Reference
🧰 Parameters
Structure of each pair passed to _.cond():
pairsRequired
Array of two-element arrays. Each inner array is [predicate, handler]. An empty array produces a function that always returns undefined.
_.cond([[pred, fn], ...])
predicatePer pair
Function tested with the same arguments the cond function receives. Any truthy return selects this pair. Falsy skips to the next pair.
[(code) => code === 404, ...]
handlerPer pair
Runs only when its predicate matches. Return value becomes the result of the cond function call. Receives identical arguments.
[(n) => "Score: " + n]
return valueFunction
The conditional function Lodash builds. Call it later with any arguments; evaluation happens at call time, not when _.cond() runs.
const route = _.cond(pairs)
Extract repeated predicates into named functions (isEven, is404) to keep pair tables readable and testable.
Hands-On
Examples Gallery
Practical _.cond() patterns with copy-ready code, sample output, and interactive Try It Yourself labs.
📚 Getting Started
Categorize numeric ranges with ordered predicate pairs.
Example 1 — Size category from a number
Map a value to Small / Medium / Large / Huge using ascending range checks and a _.stubTrue default.
Missing value
Not a number
String: hello
Other: boolean
How It Works
Lodash lang helpers like _.isNil and _.isNaN slot directly into predicate slots. Test null/NaN before generic type checks.
🚀 Beyond the Basics
Compare with imperative branching and know when each style fits.
Example 6 — cond vs switch statement
Same routing logic two ways—pick the one your team reads faster.
javascript
// Lodash cond — good for ranges and predicates
const condLabel = _.cond([
[(n) => n < 0, () => "negative"],
[(n) => n === 0, () => "zero"],
[_.stubTrue, () => "positive"]
]);
// switch — good for exact discrete values
function switchLabel(code) {
switch (code) {
case "draft": return "Draft";
case "review": return "In review";
case "live": return "Published";
default: return "Unknown";
}
}
console.log(condLabel(-2)); // "negative"
console.log(switchLabel("live")); // "Published"
📤 Console output:
negative
Published
When to prefer cond
Use _.cond() when rules are predicate-based (ranges, types, composite checks) and you want a composable function. Use switch for enum-like string/number constants.
Compare
📋 _.cond vs related patterns
Topic
_.cond
if / else if
switch
Ternary chain
Style
Functional table
Statements
Discrete cases
Expression
Reusable fn
Yes (return value)
Wrap in function
Wrap in function
Inline only
Range rules
Natural fit
Natural fit
Awkward
Hard to read
Default branch
_.stubTrue
else
default
Final : value
No match
undefined
Skip block
Fall through
N/A
🧠 How _.cond() Works
1
Build pairs table
Lodash stores your [predicate, handler] array on the returned function closure.
Setup
2
Call cond function
You invoke the function later with real arguments (score, status code, etc.).
Invoke
3
Walk pairs in order
Each predicate runs with the call arguments until one returns truthy.
Match
=
📋
Return handler result
The matched handler runs and its return value is the final result—or undefined if nothing matched.
Important
📝 Notes
Order is critical—specific predicates must appear before general ones.
Always add [_.stubTrue, handler] when you need a guaranteed default branch.
Predicates and handlers receive identical arguments from the outer call.
Handlers may return undefined intentionally—that is still a valid match result.
_.cond() does not catch errors inside predicates or handlers—wrap risky code yourself.
Pair with _.stubTrue() and lang helpers like _.isNil for readable tables.
Wrap Up
Conclusion
_.cond() turns branching rules into data: an ordered list of tests and outcomes you can name, reuse, and pass like any other function. It shines for range categorizers, status routers, and type-driven formatters.
Keep tables short, order predicates carefully, and end with _.stubTrue when every input should resolve. For simple two-way logic, a ternary or if/else may still be the clearest choice.
Use these points when building functional conditionals.
5
Core concepts
📋01
Pair table
Predicate + handler rows.
Basics
👆02
First match
Order matters.
Critical
✅03
stubTrue
Default else branch.
Pattern
📦04
Same args
Shared call signature.
API
🔀05
conforms
Next util helper.
Next step
❓ Frequently Asked Questions
_.cond() takes an array of [predicate, function] pairs and returns a new function. When you call that function, Lodash runs each predicate in order; the first one that returns a truthy value triggers its paired function, and that function's return value becomes the result.
Both the predicate and the matched handler receive the same arguments passed to the cond function. If you call getSize(15), every predicate and the chosen handler see 15 as their first argument.
_.stubTrue always returns true, so it acts as a default branch—like the final else in an if/else chain or default in a switch. Without it, no matching predicate returns undefined.
Yes. Lodash stops at the first matching predicate. Put more specific conditions before general ones, or a broad check like value > 0 will match before a narrower rule you intended to run first.
switch compares one value to case labels. _.cond() runs arbitrary predicate functions on the full argument list, which fits range checks, type guards, and object shape tests in a functional style.
Skip it for simple two-branch logic where a ternary or if/else is clearer, or when teammates are unfamiliar with functional patterns. Long cond tables can be harder to debug than explicit switch statements.
Did you know?
_.cond() is inspired by Ramda’s cond and Clojure’s cond macro. Lodash ships _.stubTrue specifically as an always-true predicate so your final pair behaves like a default clause without hard-coding () => true everywhere.