Skip to content

noUselessRegexBackrefs (JavaScript)

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

Disallow useless backreferences in regular expression literals that always match an empty string.

A backreference refers to the submatch of a previous capturing group and matches the same text as that group. JavaScript regular expression support two syntaxes:

  • \N where N is a 1-based integer that refers to the N-th declared capturing group.
  • \k<name> that refers to the capturing group named name. This syntax is only available in Unicode-aware regular expressions, i.e. regular expressions using the u or v flag.

A backreference always matches an empty string when it refers to:

  • A group that belongs to another alternate branch. In /(a)|b\1b/, the group (a) and its backreference \1 are in distinct alternate branches. /(a)|b\1/ is equivalent to (a)|b/.

  • A group that appears after the backreference. In /\1(a)/, the group (a) is declared after its backreference \1. /\1(a)/ is equivalent to (a)/.

  • A group in which the backreference is declared. In /(\1)/, the backrefernce is nested in the group it refers to. /(\1)/ is equivalent to /()/.

  • A group that is inside a negative lookaround assertion without the backreference. In /a(?!(b)).\1/, the backrefernce is in a negative assertion while its backreference is outside. /a(?!(b)).\1/ is equivalent to /a(?!(b))./.

  • A group that is declared before the backreference inside a lookbehind assertion. In /(?<=(a)\1)b/, the backreference appears after the group while they are in a lookbehind assertion. /(?<=(a)\1)b/ is equivalent to /(?<=(a))b/.

A backreference that always matches an empty string is always successfully matched and is therefore useless.

/(a)|b\1/;
code-block.js:1:7 lint/suspicious/noUselessRegexBackrefs ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

⚠ This backreference refers to a group placed in another alternate branch, making it always match an empty string.

> 1 │ /(a)|b\1/;
│ ^^
2 │

ℹ The backreference refers to this group.

> 1 │ /(a)|b\1/;
│ ^^^
2 │

ℹ The alternate separator is here.

> 1 │ /(a)|b\1/;
│ ^
2 │

ℹ Remove the backreference or place it in the same alternate branch as the group.

/\1(a)/;
code-block.js:1:2 lint/suspicious/noUselessRegexBackrefs ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

⚠ This backreference refers to a group that appears after it, making it always match an empty string.

> 1 │ /\1(a)/;
│ ^^
2 │

ℹ A backreference must refer to a group defined before its occurrence.

ℹ Remove the backreference.

/(\1)/;
code-block.js:1:3 lint/suspicious/noUselessRegexBackrefs ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

⚠ This backreference is nested within the group to which it refers, making it always match an empty string.

> 1 │ /(\1)/;
│ ^^
2 │

ℹ The group starts here.

> 1 │ /(\1)/;
│ ^^^^
2 │

ℹ Remove the backreference or place it outside the group to which it refers.

/a(?!(b)).\1/;
code-block.js:1:11 lint/suspicious/noUselessRegexBackrefs ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

⚠ This backreference refers to a group within a negated assertion, making it always match an empty string.

> 1 │ /a(?!(b)).\1/;
│ ^^
2 │

ℹ The backreference refers to this group.

> 1 │ /a(?!(b)).\1/;
│ ^^^
2 │

ℹ The negated assertion is here.

> 1 │ /a(?!(b)).\1/;
│ ^^^
2 │

ℹ Remove the backreference or place it in the negated assertion.

/(?<=(a)\1)b/;
code-block.js:1:9 lint/suspicious/noUselessRegexBackrefs ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

⚠ This backreference refers to a group that appears before itself in a lookbehind assertion, making it always match an empty string.

> 1 │ /(?<=(a)\1)b/;
│ ^^
2 │

ℹ The backreference refers to this group.

> 1 │ /(?<=(a)\1)b/;
│ ^^^
2 │

ℹ The lookbehind assertion is here.

> 1 │ /(?<=(a)\1)b/;
│ ^^^^
2 │

ℹ Remove the backreference or place it after the group it refers to.

/(a)\1/;
/(?<foo>a)\k<foo>/u;
/a(?!(b|c)\1)./;