Skip to main content

Command Palette

Search for a command to run...

Return Early: Guard Clauses Flatten Your Code

Updated
•2 min read•View as Markdown
K
the know it all

Ever opened a function and found the actual logic buried five levels deep, under a staircase of if statements? That shape has a name, the "arrow anti-pattern", and the fix is usually simple: return early.

Here's the staircase version:

function getDiscount(user, cart) {
  if (user) {
    if (user.isMember) {
      if (cart.total > 100) {
        return 0.1;
      } else {
        return 0.05;
      }
    } else {
      return 0;
    }
  } else {
    return 0;
  }
}

And here it is with guard clauses:

function getDiscount(user, cart) {
  if (!user) return 0;
  if (!user.isMember) return 0;
  if (cart.total > 100) return 0.1;
  return 0.05;
}

Same behavior, half the lines, and no nesting. The idea is to deal with the edge cases and invalid inputs first, get them out of the way, and let the "happy path" run straight down the left margin.

Why this helps:

  • Less to hold in your head. In the nested version, by the time you reach the 0.1, you're tracking three open conditions. With guards, each condition is checked and then forgotten.
  • Easier to change. Adding a new rule ("no discount for banned users") is one new line near the top, not another layer of braces.
  • Errors are obvious. Guards near the top double as documentation of what the function refuses to handle.

A caveat: don't turn this into a religion. If a function has ten guard clauses, the problem probably isn't nesting, it's that the function is doing too much.

Next time you see a pyramid of ifs, try flipping the conditions and returning early. It's one of those refactors that feels almost too easy.