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 producesundefined. Anyone consuming the return value with.upper()of their own will get aTypeErroron 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();
}