{"record":{"id":"62a5094a35f5499a","repo":"oxc-project/oxc","slug":"unexpected-var-use-let-or-const-instead","errorCode":null,"errorMessage":"Unexpected var, use let or const instead.","messagePattern":"Unexpected var, use let or const instead\\.","errorType":"validation","errorClass":"OxcDiagnostic","httpStatus":null,"severity":"warning","filePath":"crates/oxc_linter/src/rules/eslint/no_var.rs","lineNumber":12,"sourceCode":"use oxc_ast::{\n    AstKind,\n    ast::{BindingPattern, VariableDeclarationKind},\n};\nuse oxc_diagnostics::OxcDiagnostic;\nuse oxc_macros::declare_oxc_lint;\nuse oxc_span::{GetSpan, Span};\n\nuse crate::{AstNode, context::LintContext, rule::Rule, utils::has_ambient_typescript_ancestor};\n\nfn no_var_diagnostic(span: Span) -> OxcDiagnostic {\n    OxcDiagnostic::warn(\"Unexpected var, use let or const instead.\")\n        .with_help(\"Replace var with let or const\")\n        .with_label(span)\n}\n\n#[derive(Debug, Default, Clone)]\npub struct NoVar;\n\n// doc: https://github.com/eslint/eslint/blob/v9.9.1/docs/src/rules/no-var.md\n// code: https://github.com/eslint/eslint/blob/v9.9.1/lib/rules/no-var.js\n// test: https://github.com/eslint/eslint/blob/v9.9.1/tests/lib/rules/no-var.js\n\ndeclare_oxc_lint!(\n    /// ### What it does\n    ///\n    /// ECMAScript 2015 allows programmers to create variables with block scope\n    /// instead of function scope using the `let` and `const` keywords.  Block\n    /// scope is common in many other programming languages and helps\n    /// programmers avoid mistakes.","sourceCodeStart":1,"sourceCodeEnd":30,"githubUrl":"https://github.com/oxc-project/oxc/blob/e1e7af627c8843ab64044ed466b128fcc21a035b/crates/oxc_linter/src/rules/eslint/no_var.rs#L1-L30","documentation":"Diagnostic from the `no-var` rule (oxlint port of ESLint no-var). `var` declarations are function-scoped and hoisted, which causes the classic loop-closure and redeclaration bugs that `let`/`const` (block-scoped) eliminate. Oxc warns on every VariableDeclaration of kind `var`, help text 'Replace var with let or const'. Ambient TypeScript declarations (`.d.ts` `declare var`) are exempted via `has_ambient_typescript_ancestor`.","triggerScenarios":"`var count = 0;`, `for (var i = 0; ...)`, or `var config;` in any parsed source. Runs on AstKind::VariableDeclaration where kind is Var and no ambient-TS ancestor exists.","commonSituations":"Legacy codebases predating ES2015; tutorials or copied snippets using var; converting a project to stricter lint configs (oxlint `correctness`/`suspicious` presets enable this rule).","solutions":["Change `var` to `const` when the variable is assigned once.","Change `var` to `let` when it is genuinely reassigned (loop counters, accumulators).","For loop-closure patterns (`for (var i...)` with callbacks), switch to `let` so each iteration gets its own binding.","If migration is too large now, scope the rule off via oxlint config `ignore` patterns or disable comments."],"exampleFix":"// before\nvar total = 0;\nfor (var i = 0; i < items.length; i++) { total += items[i]; }\n\n// after\nlet total = 0;\nfor (let i = 0; i < items.length; i++) { total += items[i]; }","handlingStrategy":"validation","validationCode":"const usesVar = /^\\s*(var\\s)/m.test(source) || /\\bfor\\s*\\(\\s*var\\b/.test(source);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Default to `const`; switch to `let` only on true reassignment.","When modernizing legacy files, convert `var` first, then re-lint.","Keep ambient `.d.ts` declare-var code out of lint scope; the rule already exempts it."],"tags":["lint","eslint","oxlint","variables","scoping","javascript"],"backgroundTag":"no-var-prefer-let-const","analyzedSha":"e1e7af627c8843ab64044ed466b128fcc21a035b","analyzedAt":"2026-08-20T07:01:07.079Z","contentChangedAt":"2026-08-20T07:01:07.079Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}