{"record":{"id":"3ced1fc712980ec8","repo":"oxc-project/oxc","slug":"prefer-string-at-over-string-substring-when-getting-one","errorCode":null,"errorMessage":"Prefer `String#at()` over `String#substring()` when getting one character.","messagePattern":"Prefer `String#at\\(\\)` over `String#substring\\(\\)` when getting one character\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"crates/oxc_linter/src/rules/unicorn/prefer_at.rs","lineNumber":35,"sourceCode":"\nuse crate::{\n    AstNode,\n    ast_util::variable_declaration_kind,\n    context::LintContext,\n    fixer::{RuleFix, RuleFixer},\n    rule::Rule,\n    utils::{get_precedence, is_same_expression},\n};\n\nfn prefer_at_diagnostic(span: Span, method: &str) -> OxcDiagnostic {\n    OxcDiagnostic::warn(format!(\"Prefer `.at()` over `{method}`.\"))\n        .with_help(\"Use `.at()` for index access.\")\n        .with_note(\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/at\")\n        .with_label(span)\n}\n\nfn prefer_at_over_substring_diagnostic(span: Span) -> OxcDiagnostic {\n    OxcDiagnostic::warn(\n        \"Prefer `String#at()` over `String#substring()` when getting one character.\",\n    )\n    .with_help(\"Use `.at()` for index access.\")\n    .with_label(span)\n}\n\n#[derive(Debug, Default, Clone)]\npub struct PreferAt(Box<PreferAtConfig>);\n\n#[derive(Debug, Default, Clone, Deserialize, JsonSchema)]\n#[serde(rename_all = \"camelCase\", default, deny_unknown_fields)]\npub struct PreferAtConfig {\n    /// Check all index access, not just special patterns like `array.length - 1`.\n    /// When enabled, `array[0]`, `array[1]`, etc. will also be flagged.\n    check_all_index_access: bool,\n    /// List of function names to treat as \"get last element\" functions.\n    /// These functions will be checked for `.at(-1)` usage.\n    get_last_element_functions: Vec<String>,","sourceCodeStart":17,"sourceCodeEnd":53,"githubUrl":"https://github.com/oxc-project/oxc/blob/12cb5473519327bd37780f2e42bf1eade98542b6/crates/oxc_linter/src/rules/unicorn/prefer_at.rs#L17-L53","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nconst ch = str.substring(i, i + 1);\n// after\nconst ch = str.at(i);","handlingStrategy":"validation","validationCode":"// Ensure target supports String#at before adopting the rule\nif (!String.prototype.at) { throw new Error('String#at unsupported in this environment'); }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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."],"tags":["lint","javascript","strings","code-style","es2022"],"backgroundTag":"deprecated-api-usage","analyzedSha":"12cb5473519327bd37780f2e42bf1eade98542b6","analyzedAt":"2026-09-20T16:15:10.494Z","contentChangedAt":"2026-09-20T16:15:10.494Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}