Consistent Return

ID

javascript.consistent_return

Severity

low

Remediation Complexity

trivial

Remediation Risk

low

Remediation Effort

low

Resource

Reliability

Language

JavaScript

Tags

reliability, suspicious-control-flow

Description

Reports a function that mixes value-returning and bare return; statements. The mismatch usually indicates a forgotten value: one branch produced a value and another left it implicit, returning undefined. Callers cannot tell which path they are on without reading the body and the type of the call site grows hard to reason about.

The rule walks every function (declarations, expressions, arrows, methods) and collects only the return statements whose nearest enclosing function is the function under inspection — nested function bodies do not bleed into the outer.

Setters and constructors are exempt — their return statements are documented to be value-less. Getters are the inverse problem and are covered by javascript.getter_return.

Rationale

  • if (!x) return; return x.upper(); looks innocent but the early-return path produces undefined. Anyone consuming the return value with .upper() of their own will get a TypeError on the early-return path.

  • When a function deliberately has no return value, every exit should be a bare return;. Mixing the two forms hides the contract.

// Bad
function format(x) {
  if (!x) {
    return;            // implicit undefined
  }
  return x.toUpperCase();
}
format(null).length;   // TypeError

Remediation

Pick a contract and stick to it. If the function should sometimes return nothing, return null (or undefined explicitly) so callers see the intent. If it should always return a value, give the early branch a value too.

// Good — explicit null
function format(x) {
  if (!x) {
    return null;
  }
  return x.toUpperCase();
}

References