ConceptsJun 20263 min read

Conditional Assignment vs If Else Statement

Ternary-style conditional assignment versus the full if/else block — when each one earns its place in your code, and which one to reach for by default.

The short answer

Conditional Assignment over If Else Statement for most cases. When the entire job is "set this variable to one of two values," conditional assignment says exactly that in one expression.

  • Pick Conditional Assignment if picking one of two values for a single variable or return — a ternary, null-coalescing, or guard expression makes the intent obvious and keeps it an expression
  • Pick If Else Statement if the branches do genuinely different work — multiple statements, side effects, early returns, logging — where forcing it into one expression would be a crime
  • Also consider: Readability is the real metric, not line count. A nested ternary three levels deep is worse than the dumbest if/else. Pick the form that reads in one pass.

— Nice Pick, opinionated tool recommendations

What they actually are

Neither of these is a product, a library, or a thing you install — they are two ways to express a fork in the road. Conditional assignment is an expression that resolves to a value: a ternary (cond ? a : b), null-coalescing (x ?? y), Python's a if cond else b, or Kotlin's if-as-expression. It hands you a value and you bind it. The if/else statement is control flow: it runs one block or another and produces nothing on its own. The distinction is expression versus statement, and it is the whole ballgame. Conditional assignment composes — you can drop it inside a function call, an array literal, a JSX prop. A statement cannot. People treat this as a style war. It is not. It is a question of whether your fork produces a value or performs an action, and the language usually already told you the answer.

Where conditional assignment wins

The moment your code is 'set status to active or inactive based on a flag,' the if/else block is pure ceremony. You declare the variable, leave it uninitialized or mutable, write four lines, and assign the same target in two places — now a linter has to trust you set it on every path. The ternary states the intent in one breath: status = flag ? 'active' : 'inactive'. It keeps the binding immutable, keeps the assignment target named once, and drops cleanly into a return, a config object, or a template. It also resists rot: nobody sneaks a console.log or a metrics call into a branch of an expression, because there are no branches to sneak into. For value selection — defaults, fallbacks, normalizing one of two inputs — this is the correct tool and the if/else is just a longer way to be wrong.

Where if/else earns it back

Conditional assignment collapses the instant the branches stop being values. Two statements per side, an early return, a thrown error, a log line, an await with cleanup — cram any of that into a ternary and you get an unreadable comma-operator horror or an immediately-invoked arrow function that fools nobody. This is where the if/else is not a compromise, it is correct. It gives each branch a real scope to do real work. The failure mode of the ternary crowd is nesting: a ? b : c ? d : e ? f : g is a decision tree pretending to be a line, and it is worse than the most verbose block. If you find yourself reaching for a second colon, stop and write the if/else — or a lookup table. The statement also wins when the condition guards a side effect that produces no value at all, because then there is nothing to assign.

The verdict, sharpened

Stop arguing this in the abstract and ask one question: does this fork produce a value, or perform an action? Value — conditional assignment, every time; the if/else block is line-count theater that mutates where it should bind and repeats the target where it should name it once. Action — if/else, and don't let a ternary zealot talk you into an IIFE. The trap on both sides is the same: complexity smuggled into the wrong shape. A nested ternary is a flowchart cosplaying as an expression; a five-line if/else around a single assignment is a paragraph where a phrase would do. Default to conditional assignment for selection because it is honest about what it does and resists later abuse. Escalate to if/else the moment branches diverge in behavior. The good engineer doesn't have a favorite — they read the fork and pick the shape that matches it.

Quick Comparison

FactorConditional AssignmentIf Else Statement
Produces a valueYes — it is an expression you can compose anywhereNo — it is control flow that runs blocks
Multi-statement / side-effect branchesForces ugly IIFE or comma hacksNative — each branch gets a real scope
Immutability of the bound targetBinds once, stays constUsually needs a mutable, two-site assignment
Readability under deep nestingDegrades fast — nested ternaries are a flowchart in disguiseStays legible with else-if chains
Default for simple value selectionOne line, intent-obvious, rot-resistantCeremony — four lines to say one thing

The Verdict

Use Conditional Assignment if: You are picking one of two values for a single variable or return — a ternary, null-coalescing, or guard expression makes the intent obvious and keeps it an expression.

Use If Else Statement if: The branches do genuinely different work — multiple statements, side effects, early returns, logging — where forcing it into one expression would be a crime.

Consider: Readability is the real metric, not line count. A nested ternary three levels deep is worse than the dumbest if/else. Pick the form that reads in one pass.

🧊
The Bottom Line
Conditional Assignment wins

When the entire job is "set this variable to one of two values," conditional assignment says exactly that in one expression. The if/else block scatters the same intent across five lines, repeats the assignment target twice, and invites someone to wedge an unrelated side effect into a branch later. Default to conditional assignment for value selection; reach for if/else only when branches actually do different work.

Related Comparisons

Disagree? nice@nicepick.dev