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 class declaration creates a single binding for the class. Code anywhere in scope is entitled to call new Foo() and expect an instance of Foo. After reassignment, Foo may be any value (including undefined) and new 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 let from 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(); } };

References