Skip to content
JavaScript js fundamentals 4 min read

The Ternary Operator

The ternary operator (? :) is JavaScript’s only operator that takes three operands. It evaluates a condition and returns one of two values, making it the most concise way to express a choice. Because it is an expression rather than a statement, you can use it anywhere a value is expected — inside assignments, function arguments, template literals, and JSX. Used well it makes code shorter and clearer; nested carelessly it becomes a puzzle.

Syntax

The form is always condition ? valueIfTruthy : valueIfFalsy. JavaScript evaluates the condition, coercing it to a boolean, then returns the expression after ? when truthy or the expression after : when falsy.

const age = 20;
const status = age >= 18 ? "adult" : "minor";
console.log(status);

Output:

adult

Only the chosen branch is evaluated — the other is skipped entirely. This short-circuiting means side effects in the untaken branch never run, which matters when a branch calls a function or performs a computation.

const fallback = () => {
  console.log("fallback ran");
  return "default";
};

const value = true ? "primary" : fallback();
console.log(value);

Output:

primary

Notice fallback ran is absent — the falsy branch was never touched.

Ternary vs if statement

An if statement controls flow; the ternary produces a value. They are not interchangeable. Reach for the ternary when you are picking between two values; reach for if when you are deciding between two actions or running multiple statements.

ConcernTernary ? :if statement
Returns a valueYes (it’s an expression)No (it’s a statement)
Use inline (in assignment, JSX, template)YesNo
Run multiple statements per branchNoYes
Best forChoosing between two valuesBranching program flow
// Good: choosing a value
const greeting = isLoggedIn ? `Welcome back, ${name}` : "Please sign in";

// Better as an if: doing things
if (isLoggedIn) {
  trackLogin(name);
  renderDashboard();
} else {
  redirectToLogin();
}

Tip: If you ever write x ? doThing() : undefined purely for the side effect, you want an if statement instead. The ternary is for values, not for triggering one-sided actions.

Common uses

Inline assignment and arguments

The ternary shines when a value depends on a condition. It keeps the decision next to where the value is used.

const discount = isMember ? 0.1 : 0;
const price = base * (1 - discount);

console.log(formatCurrency(total > 100 ? total * 0.95 : total));

Inside template literals and JSX

Because if cannot appear inside an expression, the ternary is the standard tool for conditional text in template literals and conditional rendering in JSX-style code.

const items = 1;
const label = `${items} item${items === 1 ? "" : "s"} in cart`;
console.log(label);

Output:

1 item in cart
// React/JSX: pick which element to render
function Status({ online }) {
  return <span>{online ? "🟢 Online" : "⚪ Offline"}</span>;
}

Default-style values

A ternary can express a fallback, though for nullish defaults the ?? operator is usually cleaner.

const name = input ? input.trim() : "Anonymous";
// For null/undefined-only fallbacks, prefer:
const port = config.port ?? 3000;

Chaining and readability

Ternaries can be chained because the falsy branch can itself be another ternary. This mimics an if / else if / else ladder, but readability degrades fast.

const grade =
  score >= 90 ? "A"
  : score >= 80 ? "B"
  : score >= 70 ? "C"
  : "F";

console.log(grade);

When formatted as a vertical ladder like above, a two- or three-level chain stays readable. Beyond that, the logic is hard to scan, and a real branching structure — an if/else if chain, a switch, or a lookup object — communicates intent better.

// Clearer than a deep ternary chain for discrete mappings
const labels = { draft: "Draft", review: "In review", live: "Published" };
const display = labels[state] ?? "Unknown";

Warning: Avoid nesting a ternary inside the truthy branch (a ? b ? c : d : e). It reads ambiguously and is a frequent source of bugs. If you must chain, keep the nesting in the falsy position so it reads top-to-bottom.

Operator precedence is also a common pitfall. The ternary has very low precedence, so wrap it in parentheses when embedding it in larger expressions.

// Surprising: + binds tighter than ?:, but assignment is fine here.
const message = "Total: " + (paid ? "received" : "pending");
console.log(message);

Output:

Total: pending

Best Practices

  • Use the ternary to choose between two values; use if to choose between two actions or multiple statements.
  • Keep each branch a simple expression — extract complex logic into a named variable or function first.
  • Limit chains to two or three levels and format them as a vertical ladder for scanability.
  • Never nest a ternary in the truthy branch; if you chain, nest only in the falsy branch.
  • Prefer ?? for null/undefined defaults and lookup objects for discrete value maps over deep ternary chains.
  • Wrap ternaries in parentheses when combining them with other operators to avoid precedence surprises.
Last updated June 1, 2026
Was this helpful?