oxc-project/oxc · warning · OxcDiagnostic

Use a regular expression literal instead of the `RegExp` con

Error message

Use a regular expression literal instead of the `RegExp` constructor.

What it means

This is the oxlint `eslint/prefer-regex-literals` rule firing on a `new RegExp(...)` (or bare `RegExp(...)`) call whose arguments are statically known, meaning a regex literal would work identically. The diagnostic constructor at prefer_regex_literals.rs:20 is emitted whenever the rule sees a `RegExp` callee with string (or regex-literal) arguments. It is a port of ESLint's prefer-regex-literals and exists because literal regexes are parsed once at compile time, are easier to read, and avoid accidental runtime recompilation.

Source

Thrown at crates/oxc_linter/src/rules/eslint/prefer_regex_literals.rs:20

use serde::{Deserialize, Serialize};

use oxc_ast::{
    AstKind,
    ast::{Argument, Expression},
};
use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint;
use oxc_span::Span;

use crate::{
    AstNode,
    context::LintContext,
    rule::{DefaultRuleConfig, Rule},
    utils::{is_regexp_callee, is_string_raw_member_expression},
};

fn unexpected_regexp_diagnostic(span: Span) -> OxcDiagnostic {
    OxcDiagnostic::warn("Use a regular expression literal instead of the `RegExp` constructor.")
        .with_label(span)
}

fn unexpected_redundant_regexp_diagnostic(span: Span) -> OxcDiagnostic {
    OxcDiagnostic::warn(
        "Regular expression literal is unnecessarily wrapped within a `RegExp` constructor.",
    )
    .with_label(span)
}

fn unexpected_redundant_regexp_with_flags_diagnostic(span: Span) -> OxcDiagnostic {
    OxcDiagnostic::warn(
        "Use regular expression literal with flags instead of the `RegExp` constructor.",
    )
    .with_label(span)
}

#[derive(Debug, Default, Clone, Serialize, Deserialize, JsonSchema)]

View on GitHub (pinned to e1e7af627c)

Solutions

  1. Replace the constructor call with a regex literal: `new RegExp("abc", "i")` becomes `/abc/i`.
  2. If the pattern is built from truly static pieces, inline the final pattern as a literal.
  3. If the pattern genuinely must stay dynamic, keep `new RegExp` and disable the rule for the line with `// oxlint-disable-next-line prefer-regex-literals`.
  4. Turn the rule off in `.oxlintrc.json` via `"rules": { "prefer-regex-literals": "off" }` if your team disagrees with it.

Example fix

// before
const re = new RegExp("^\\d+$", "i");

// after
const re = /^\d+$/i;
Defensive patterns

Strategy: validation

Validate before calling

# fail early in CI on RegExp constructor calls with static args
rg -n --pcre2 'new\s+RegExp\(\s*["'"'"']' src/ && echo 'prefer-regex-literals violations' && exit 1

Prevention

When it happens

Trigger: Calling `RegExp("foo")`, `new RegExp("foo", "i")`, or `RegExp('a' + 'b')` where all arguments are string literals or static concatenations of literals. The rule's `is_regexp_callee`/`is_string_raw_member_expression` utils (imported at the top of prefer_regex_literals.rs) gate the check to callee name `RegExp` with string-only arguments.

Common situations: Code copied from older ES5 codebases that predate universal regex-literal support; dynamically built patterns where the dynamic part was later removed; generated code. Teams enabling the `eslint` plugin preset in `.oxlintrc.json` without remembering this rule is on.

Related errors


AI-assisted analysis of oxc-project/oxc@e1e7af627c (2026-08-20). Data as JSON: /api/errors/12b98d69816a5633. Report an issue: GitHub.