Prefer const

ID

javascript.prefer_const

Severity

info

Remediation Complexity

auto_fix

Remediation Risk

low

Remediation Effort

low

Resource

Best Practice

Language

JavaScript

Tags

best-practice, modernization

Description

Reports a let-declared binding that is never reassigned (no plain assignment, no compound assignment, no ++ / --). The recommendation is to declare such bindings with const so the immutable contract is visible at the declaration site, the engine can apply additional optimisations, and the human reader doesn’t have to scan the rest of the scope to confirm the value never changes.

The rule is conservative — it skips:

  • Bindings without an initializer (let x;). Those need a split-then-assign analysis the rule does not perform.

  • Destructuring patterns (let {a} = obj). Each sub-binding has its own symbol; mixing const-eligible and reassigned ones in the same destructuring is awkward to remediate.

  • Bindings declared in the iteration head of for…in / for…of. Those are reassigned on every iteration even though the binding looks unchanged in user code.

Rationale

  • const documents intent at the declaration site. A reader sees one line and knows the binding will never change.

  • Modern engines elide some checks for const-bound values. The optimisation is small per-call but compounds in hot loops.

  • Type checkers and bundlers do better refactoring (e.g. inlining small constants) when the binding is const.

// Bad
let cache = new Map();   // never reassigned

// Good
const cache = new Map();

Remediation

Change let to const. If a future change adds a reassignment, the engine will throw immediately and the developer can revert the keyword — that’s a feature, not a regression.

// Good
const port = process.env.PORT ?? 3000;
const greeting = `Hello, ${name}`;

References