No Class Reassignment
ID |
javascript.no_class_assign |
Severity |
low |
Remediation Complexity |
trivial |
Remediation Risk |
low |
Remediation Effort |
low |
Resource |
Reliability |
Language |
JavaScript |
Tags |
reliability, suspicious-assignment |
Description
Reports assignments to a binding declared by a class declaration. After class Foo {}, the statement Foo = something; replaces the binding so subsequent uses of new Foo(…) or instanceof Foo no longer reach the declared class. The reassignment is legal in non-strict mode and silent (it throws in strict mode), so it is a perfect breeding ground for typos.
Property assignments such as Foo.bar = …, destructuring targets and assignments to other binding kinds (let / const / var / function / parameter / import) are out of scope — they are covered by sibling rules.
Rationale
-
A
classdeclaration creates a single binding for the class. Code anywhere in scope is entitled to callnew Foo()and expect an instance ofFoo. After reassignment,Foomay be any value (includingundefined) andnew Foo()either throws or constructs the wrong thing. -
If the original class needs to be replaced, that intent should be explicit — either declare it with
letfrom the start, or rename the new value.
// Bad
class Cache {
constructor(key) { this.key = key; }
}
// later, in a refactor:
Cache = new Map(); // typo — meant `cacheStore`. Cache() now is a Map.
Remediation
If the binding really must change, declare it with let so the intent is visible. If the assignment was a typo, rename to a fresh identifier.
// Good
let Cache = class { constructor(k) { this.key = k; } };
Cache = class { constructor(k) { this.key = k.toUpperCase(); } };