# Guard clauses and the arrow anti-pattern

> Check failure conditions first and return early, so the main path stays unindented instead of disappearing into nested ifs.

Concept · Code design · https://levelcode.org/concepts/guard-clauses

The **arrow anti-pattern** is code whose nested conditionals push the real work further and further to the right, until the indentation forms an arrow. Each `else` sits far from its `if`, and to understand any line you must hold every enclosing condition in your head.

A **guard clause** fixes it: test each precondition at the top, handle the failure (return, throw, `continue`), and let the main path run down the left margin.

## Before and after

```ts
// Arrow
function shippingLabel(order: Order | null): string {
  if (order) {
    if (order.status === 'paid') {
      if (order.address) {
        return formatLabel(order.address)
      } else {
        throw new Error('missing address')
      }
    } else {
      throw new Error('order not paid')
    }
  } else {
    throw new Error('no order')
  }
}

// Guard clauses
function shippingLabel(order: Order | null): string {
  if (!order) throw new Error('no order')
  if (order.status !== 'paid') throw new Error('order not paid')
  if (!order.address) throw new Error('missing address')
  return formatLabel(order.address)
}
```

Same behaviour; each rule is now one independent line, and adding a fourth check doesn't deepen anything. In TypeScript, guards also **narrow types**: after `if (!order) throw …`, the compiler knows `order` isn't null.

## Why it works

- Readers see the preconditions as a list, then the main logic, with no matching of distant braces.
- Failure handling sits next to the condition that causes it.
- In Go this is simply idiomatic: `if err != nil { return … }` is a guard clause, and Go style asks you to keep the normal path unindented.

## Related techniques

- `continue` at the top of a loop body instead of wrapping the body in an `if`.
- Extract a deeply nested block into a function with its own guards.
- Replace a long `if/else if` chain on a type with a lookup table or polymorphism.

Some old style guides demanded a "single exit point" per function. That rule comes from languages without automatic cleanup; with `defer`, `finally` or RAII, early returns are safe. The [clean code lesson](https://levelcode.org/roadmaps/software-engineer/clean-code) shows the same refactoring in Go.
