oxc-project/oxc · warning · OxcDiagnostic

Prefer String#slice() over String#{method_name}()

Error message

Prefer String#slice() over String#{method_name}()

What it means

This is the oxlint rule `unicorn/prefer-string-slice`. It flags calls to the legacy substring methods `String#substr(start, length)` (deprecated) and `String#substring(a, b)` (with its argument-swapping and negative-clamping quirks) on receivers the rule can resolve to strings, and recommends `String#slice()`, which has consistent index semantics everywhere.

Source

Thrown at crates/oxc_linter/src/rules/unicorn/prefer_string_slice.rs:12

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

use crate::{AstNode, context::LintContext, rule::Rule};

fn prefer_string_slice_diagnostic(span: Span, method_name: &str) -> OxcDiagnostic {
    OxcDiagnostic::warn(format!("Prefer String#slice() over String#{method_name}()"))
        .with_label(span)
}

#[derive(Debug, Default, Clone)]
pub struct PreferStringSlice;

declare_oxc_lint!(
    /// ### What it does
    ///
    /// Prefer [`String#slice()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/slice) over [`String#substr()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/substr) and [`String#substring()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/substring).
    ///
    /// ### Why is this bad?
    ///
    /// [`String#substr()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/substr) and [`String#substring()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/substring) are the two lesser known legacy ways to slice a string. It's better to use [`String#slice()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/slice) as it's a more popular option with clearer behavior that has a consistent [`Array` counterpart](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice).
    ///
    /// ### Examples
    ///
    /// Examples of **incorrect** code for this rule:

View on GitHub (pinned to e1e7af627c)

Solutions

  1. Rewrite `str.substr(start, len)` as `str.slice(start, start + len)`.
  2. Rewrite `str.substring(a, b)` as `str.slice(a, b)` — but only after confirming `a <= b` and neither argument is negative (otherwise semantics differ).
  3. Run `oxlint --fix` where a fixer applies, and hand-review each conversion for the negative/swap cases.
  4. Disable with `"unicorn/prefer-string-slice": "off"` if you are maintaining a legacy codebase deliberately matched to old behavior.

Example fix

// before
const tail = s.substring(1);
const head = s.substr(0, 3);

// after
const tail = s.slice(1);
const head = s.slice(0, 3);
Defensive patterns

Strategy: validation

Validate before calling

// Standardize on slice for all substring extraction
const head = s.slice(0, 3);
const tail = s.slice(-3);
// CI: npx oxlint --deny-warn unicorn/prefer-string-slice src/

Prevention

When it happens

Trigger: `str.substr(0, 5)`, `str.substring(1, 4)`, or `str.substring(4)` on a receiver recognized as a string (via member-expression checks in the rule's `run`). Computed receivers or optional chains are skipped.

Common situations: Porting old JS/jQuery-era code or snippets copied from MDN legacy examples; the real hazard is `substring`'s behavior of swapping arguments when `a > b` and treating negatives as 0, which differs from every other language — reviewers ask for `slice` to remove the footgun. Note `substr`'s second argument is a length, not an end index, so converting requires arithmetic.

Related errors


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