Skip to content

noUselessRecursion (JavaScript)

Language JavaScript (and super languages)
biome.json
{
"linter": {
"rules": {
"nursery": {
"noUselessRecursion": "error"
}
}
}
}

Disallow functions that return a call to themselves when a loop can do the same work.

A recursive function is a function that calls itself. Each of these calls uses a bit more memory until it finishes, so a function that calls itself too many times in a row crashes the program with a “Maximum call stack size exceeded” error. When the function only returns the result of calling itself again, a loop such as while can do the same work without that limit, and is often easier to follow.

This rule only reports return name(...) inside a function declared with the function keyword and a name, where name is that function’s own name. It doesn’t report other kinds of recursion, such as calls whose result is used in a larger expression, calls inside methods or arrow functions, or calls inside function* functions.

It also doesn’t report calls in these places, because code there runs after each call finishes, so a loop can’t replace the call directly:

  • inside a try statement;
  • after a using or await using declaration in the same block, or in a block that contains the call;
  • inside a for or for...of loop that declares its variable with using or await using, such as for (using file of files).
function findRoot(node) {
if (node.parent) {
return findRoot(node.parent);
}
return node;
}
code-block.js:3:16 lint/nursery/noUselessRecursion ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

ℹ This function returns a call to itself, which can be replaced with a loop.

1 │ function findRoot(node) {
2 │ if (node.parent) {
> 3 │ return findRoot(node.parent);
│ ^^^^^^^^
4 │ }
5 │

ℹ Each nested call uses more memory, and too many nested calls crash the program with a stack overflow error.

ℹ Use a loop, such as while, that updates the values on each step instead of calling the function again.

ℹ This rule belongs to the nursery group, which means it is not yet stable and may change in the future. Visit https://biomejs.dev/linter/#nursery for more information.

function findRoot(node) {
while (node.parent) {
node = node.parent;
}
return node;
}
function flatten(value) {
if (Array.isArray(value)) {
return value.flatMap((item) => flatten(item));
}
return [value];
}
function sum(list) {
return list.length === 0 ? 0 : list[0] + sum(list.slice(1));
}