oxc-project/oxc · warning
Prefer `String#at()` over `String#substring()` when getting…
Error message
Prefer `String#at()` over `String#substring()` when getting one character.
What it means
This is a lint diagnostic from the oxlint rule `unicorn/prefer-at`. It fires when `String#substring()` (or a slice-like call) is used just to fetch a single character, suggesting `String#at()` instead, which is clearer and supports negative indices. The library throws it to modernize character-access code.
Solutions
- Replace `s.substring(i, i + 1)` with `s.at(i)` (or `.at(-n)` for offsets from the end).
- Apply the rule's auto-fix when available.
- Target ES2022+ (or polyfill String.prototype.at) if runtime support for very old environments is required, otherwise disable the rule.
Example fix
// before const ch = str.substring(i, i + 1); // after const ch = str.at(i);
Defensive patterns
Strategy: validation
Validate before calling
// Ensure target supports String#at before adopting the rule
if (!String.prototype.at) { throw new Error('String#at unsupported in this environment'); } Prevention
- Default to `.at(i)` for single-character access instead of substring/slice.
- Set browserslist/ES2022 targets so modern string APIs are safe to use.
- Run `oxlint --fix` in CI to keep single-character substring usage out of the codebase.
When it happens
Trigger: oxlint detects a call to `.substring(...)` on a string where the arguments indicate only one character is being extracted (e.g. `s.substring(i, i+1)` or `s.substring(i, i+1)`-equivalent single-index access), via check_substring -> prefer_at_over_substring_diagnostic.
Common situations: Legacy string-parsing code written before `String#at()` (ES2022) existed; codebases ported from older JS targets; fresh oxlint adoption with the unicorn preset flags old idioms.
Understand the failure class
Background: "is deprecated and will be removed" — deprecation warnings for old API names, keywords, and options, and how to migrate before the removal release — this error's family across 29 libraries.
Related errors
- Prefer a single `.flatMap(…)` over `.filter(…).flatMap(…)`.
- Unexpected empty static blocks
- A regular expression literal can be confused with '/='.
- Avoid nesting promises.
- Avoid unnecessary use of .
AI-assisted analysis of oxc-project/oxc@12cb547351 (2026-09-20).
Data as JSON: /api/errors/3ced1fc712980ec8.
Report an issue: GitHub.
Appendix: source
Thrown at crates/oxc_linter/src/rules/unicorn/prefer_at.rs:35
use crate::{
AstNode,
ast_util::variable_declaration_kind,
context::LintContext,
fixer::{RuleFix, RuleFixer},
rule::Rule,
utils::{get_precedence, is_same_expression},
};
fn prefer_at_diagnostic(span: Span, method: &str) -> OxcDiagnostic {
OxcDiagnostic::warn(format!("Prefer `.at()` over `{method}`."))
.with_help("Use `.at()` for index access.")
.with_note("https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/at")
.with_label(span)
}
fn prefer_at_over_substring_diagnostic(span: Span) -> OxcDiagnostic {
OxcDiagnostic::warn(
"Prefer `String#at()` over `String#substring()` when getting one character.",
)
.with_help("Use `.at()` for index access.")
.with_label(span)
}
#[derive(Debug, Default, Clone)]
pub struct PreferAt(Box<PreferAtConfig>);
#[derive(Debug, Default, Clone, Deserialize, JsonSchema)]
#[serde(rename_all = "camelCase", default, deny_unknown_fields)]
pub struct PreferAtConfig {
/// Check all index access, not just special patterns like `array.length - 1`.
/// When enabled, `array[0]`, `array[1]`, etc. will also be flagged.
check_all_index_access: bool,
/// List of function names to treat as "get last element" functions.
/// These functions will be checked for `.at(-1)` usage.
get_last_element_functions: Vec<String>,View on GitHub (pinned to 12cb547351)