The Thinking Behind eslint-plugin-immutable-2
eslint-plugin-immutable-2 was built around a simple goal: make safer TypeScript patterns easier to adopt at scale without turning linting into noise.
The core motivationβ
Most TypeScript codebases still accumulate mutation in the places where the language and standard library make it easy: object property writes, let, mutable array types, exception-style control flow, and host APIs such as Date, URL, Map, Set, Storage, and Headers.
This plugin tries to close that gap by doing three things:
- Detect mutation-heavy patterns reliably.
- Offer clear, actionable diagnostics instead of vague βbad styleβ warnings.
- Provide a preset ladder that teams can adopt gradually rather than all at once.
Design constraints we intentionally acceptedβ
1) Performance over clevernessβ
Rules run on every save. If a rule needs expensive type-checker calls in hot paths, it can become a drag on the whole developer workflow.
So we bias toward:
- syntax-first detection where possible,
- narrow AST selectors,
- type-aware lookups only where they materially improve correctness.
2) Correctness over aggressive autofixesβ
A fast autofix that changes runtime behavior is a bug.
When we can guarantee safety, we emit fix.
When a transformation is likely correct but not universally safe, we emit suggest.
This keeps trust high: developers know auto-applied changes are meant to be safe-by-default.
3) Documentation as part of the rule contractβ
A rule without clear documentation creates churn.
Every rule is expected to explain:
- the specific anti-pattern it flags,
- the safer alternative,
- concrete incorrect/correct examples,
- whether type information is required.
Long-term directionβ
The roadmap is to keep broadening immutability coverage while preserving practical adoption paths:
- low-friction presets for gradual rollout,
- stricter presets for mature codebases,
- targeted mutation coverage for both core language constructs and mutable host APIs,
- focused migration guidance in docs and examples.
If a rule cannot be explained explicitly, implemented performantly, and fixed safely, it does not belong in this plugin.
