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
-
constdocuments 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}`;