Skip to content

docs: list the differences from Immer and describe patch behavior - #197

Merged
unadlib merged 4 commits into
mainfrom
docs/immer-differences
Oct 9, 2026
Merged

unadlib merged 4 commits into
mainfrom
docs/immer-differences

Conversation

@unadlib

@unadlib unadlib commented Oct 9, 2026

Copy link
Copy Markdown
Owner

Part of #168.

The differences from Immer were spread over a v1 feature table, two FAQ entries, the create() reference, the Patches guide and the test files, and the table had not been checked against a current Immer. This PR collects them on the Comparison with Immer page, checked against Immer 11.1.18, and describes how Mutative generates and applies patches. It covers the two roadmap items "Document the intentional differences in one place" and "Document patch behavior and important differences from Immer".

  1. Comparison with Immer. The page now has a summary table, a table that maps every export of Immer 11.1.18 to Mutative, and sections on defaults and configuration, drafts, patches, and the Immer failures that Mutative's tests pin. Each section also names the behaviors that both libraries share where it is easy to assume otherwise. The performance section is unchanged.
  2. Patch behavior. The Patches guide gets a reference section: operations and paths, order, values, arrays, Maps, Sets, moved drafts, apply() and JSON Patch compatibility.
  3. README. The difference table in the README is replaced by the checked one, which links the page.
  4. Links. The FAQ of the README and of the website and both Immer migration guides link the page.

How the statements were checked

Every behavior that the pages state was run against Immer 11.1.18 and against main at 243ff7f in 97 cases:

  • defaults and plugins, async recipes, class instances, Map and Set subclasses and Set methods;
  • freezing and copying, current() and original(), nested producers, returned values and Map iteration;
  • the patches and inverse patches of objects, arrays, Maps, Sets and roots;
  • apply() with reserved paths, appending, unsupported operations, copies, drafts and undo after redo.

The checks changed several statements:

  • "Complete freeze data": both libraries freeze nested data deeply, unchanged parts included, and freeze Map and Set instances so that their mutators throw. The difference left is that Mutative also freezes the objects used as Map keys.
  • "async draft function": holds. Immer 11 throws, because it takes the returned Promise as a new value while the draft changed.
  • "new Set methods": holds, and the page shows how. On Immer's Set drafts, union() of a draft of new Set([1, 2]) with new Set([3]) returns Set {3}.
  • Two limits shared with Immer: an iteration over a Map draft that starts before the first change, and an undo after a redo for objects in a Set. The FAQ and the Patches guide describe both as Mutative behavior; the page says Immer behaves the same.
  • Array patches differ only where an array gets shorter, under the default arrayLengthAssignment; with arrayLengthAssignment: false they equal Immer's.
  • Changed items of a Set: without membership changes, they are positional replace patches in Mutative and remove-and-add pairs in Immer.
  • Cited Immer failures: some tests in immer-non-support.test.ts pass with Immer 11.1.18 today, so the page cites only cases that still fail there: a draft that escapes into the next state, Map keys that stay mutable after freezing, Set methods, and Map and Set subclasses.

The website builds, and its link check passes for 49 pages, including the anchors of the new links. In Chromium at 1280 px, the two tables render without overflow.

@unadlib unadlib mentioned this pull request Oct 9, 2026
@github-actions

github-actions Bot commented Oct 9, 2026

Copy link
Copy Markdown

Coverage after merging docs/immer-differences into main will be

100.00%

Coverage Report
FileStmtsBranchesFuncsLinesUncovered Lines
src
   apply.ts100%100%100%100%
   array.ts100%100%100%100%
   constant.ts100%100%100%100%
   create.ts100%100%100%100%
   current.ts100%100%100%100%
   draft.ts100%100%100%100%
   draftify.ts100%100%100%100%
   error.ts100%100%100%100%
   index.ts100%100%100%100%
   interface.ts100%100%100%100%
   internal.ts100%100%100%100%
   makeCreator.ts100%100%100%100%
   map.ts100%100%100%100%
   original.ts100%100%100%100%
   patch.ts100%100%100%100%
   rawReturn.ts100%100%100%100%
   set.ts100%100%100%100%
   unsafe.ts100%100%100%100%
src/utils
   cast.ts100%100%100%100%
   copy.ts100%100%100%100%
   deepFreeze.ts100%100%100%100%
   draft.ts100%100%100%100%
   finalize.ts100%100%100%100%
   forEach.ts100%100%100%100%
   index.ts100%100%100%100%
   mark.ts100%100%100%100%
   marker.ts100%100%100%100%
   proto.ts100%100%100%100%

@unadlib
unadlib merged commit d96aa98 into main Oct 9, 2026
9 checks passed
@unadlib
unadlib deleted the docs/immer-differences branch October 9, 2026 16:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant