kolodny/immutability-helper is tracked by TopGit as an open-source project, with 5.2k stars on GitHub, written primarily in TypeScript. mutate a copy of data without changing the original source
Snapshot summary built from the project's own GitHub metadata — there's no written TopGit review yet. The page will update automatically when a full review is published.
WHY NO REVIEW YET
TopGit writes full reviews for the most-starred, most-requested repositories. This page is a snapshot until then — see the READ ME tab for the original README in full.
Note that this module has nothing to do with React. However, since this module
is most commonly used with React, the docs will focus on how it can be used with
React.
Overview
React lets you use whatever style of data management you want, including
mutation. However, if you can use immutable data in performance-critical parts
of your application it's easy to implement a fast shouldComponentUpdate() method
to significantly speed up your app.
Dealing with immutable data in JavaScript is more difficult than in languages
designed for it, like Clojure. However, we've provided a
simple immutability helper, update(), that makes dealing with this type of
data much easier, without fundamentally changing how your data is represented.
You can also take a look at Facebook's
Immutable.js and React’s
Using Immutable Data Structures section for more
detail on Immutable.js.
The Main Idea
If you mutate data like this:
myData.x.y.z = 7;
// or...
myData.a.b.push(9);
You have no way of determining which data has changed since the previous copy
has been overwritten. Instead, you need to create a new copy of myData and
change only the parts of it that need to be changed. Then you can compare the
old copy of myData with the new one in shouldComponentUpdate() using
triple-equals:
Unfortunately, deep copies are expensive, and sometimes impossible. You can
alleviate this by only copying objects that need to be changed and by reusing
the objects that haven't changed. Unfortunately, in today's JavaScript this can
be cumbersome:
While this is fairly performant (since it only makes a shallow copy of log n
objects and reuses the rest), it's a big pain to write. Look at all the
repetition! This is not only annoying, but also provides a large surface area
for bugs.
update()
update() provides simple syntactic sugar around this pattern to make writing
this code easier. This code becomes:
While the syntax takes a little getting used to (though it's inspired by
MongoDB's query language) there's no redundancy, it's statically analyzable and it's not much more typing
than the mutative version.
The $-prefixed keys are called commands. The data structure they are
"mutating" is called the target.
Available Commands
{$push: array}push() all the items in array on the target.
{$unshift: array}unshift() all the items in array on the target.
{$splice: array of arrays} for each item in arrays call splice() on
the target with the parameters provided by the item. Note: The items in
the array are applied sequentially, so the order matters. The indices of the
target may change during the operation.
{$set: any} replace the target entirely.
{$toggle: array of strings} toggles a list of boolean fields from the
target object.
{$unset: array of strings} remove the list of keys in array from the
target object.
{$merge: object} merge the keys of object with the target.
{$apply: function} passes in the current value to the function and
updates it with the new returned value.
{$add: array of objects} add a value to a Map or Set. When adding to a
Set you pass in an array of objects to add, when adding to a Map, you pass
in [key, value] arrays like so:
update(myMap, {$add: [['foo', 'bar'], ['baz', 'boo']]})
{$remove: array of strings} remove the list of keys in array from a Map
or Set.
Shorthand $apply syntax
Additionally, instead of a command object, you can pass a function, and it will
be treated as if it was a command object with the $apply command:
update({a: 1}, {a: function}). That example would be equivalent to
update({a: 1}, {a: {$apply: function}}).
Limitations
:warning: update only works for data properties, not for accessor properties defined with Object.defineProperty. It just does not see the latter, and therefore might create shadowing data properties which could break application logic depending on setter side effects. Therefore update should only be used on plain data objects that only contain data properties as descendants.
Arrays can be indexed into with runtime variables via the ES2015
Computed Property Names
feature. An object property name expression may be wrapped in brackets [] which
will be evaluated at runtime to form the final property name.
// Delete at a specific index, no matter what value is in it
update(state, { items: { $splice: [[index, 1]] } });
Autovivification
Autovivification is the auto creation of new arrays and objects when needed. In
the context of javascript that would mean something like this
const state = {}
state.a.b.c = 1; // state would equal { a: { b: { c: 1 } } }
Since javascript doesn't have this "feature", the same applies to
immutability-helper. The reason why this is practically impossible in
javascript and by extension immutability-helper is the following:
var state = {}
state.thing[0] = 'foo' // What type should state.thing have? Should it be an object or array?
state.thing2[1] = 'foo2' // What about thing2? This must be an object!
state.thing3 = ['thing3'] // This is regular js, this works without autovivification
state.thing3[1] = 'foo3' // Hmm, notice that state.thing2 is an object, yet this is an array
state.thing2.slice // should be undefined
state.thing3.slice // should be a function
If you need to set something deeply nested and don't want to have to set each
layer down the line, consider using this technique which is shown with a
contrived example:
var state = {}
var desiredState = {
foo: [
{
bar: ['x', 'y', 'z']
},
],
};
const state2 = update(state, {
foo: foo =>
update(foo || [], {
0: fooZero =>
update(fooZero || {}, {
bar: bar => update(bar || [], { $push: ["x", "y", "z"] })
})
})
});
console.log(JSON.stringify(state2) === JSON.stringify(desiredState)) // true
// note that state could have been declared as any of the following and it would still output true:
// var state = { foo: [] }
// var state = { foo: [ {} ] }
// var state = { foo: [ {bar: []} ] }
You can also choose to use the extend functionality to add an $auto and
$autoArray command:
Note that original in the function above is the original object, so if you
plan making a mutation, you must first shallow clone the object. Another option
is to use update to make the change
return update(original, { foo: {$set: 'bar'} })
If you don't want to mess around with the globally exported update function
you can make a copy and work with that copy:
Does kolodny/immutability-helper have a project website?
No homepage URL was recorded for kolodny/immutability-helper in TopGit's last sync. The README tab above frequently contains screenshots and demo links, or check the repository description on GitHub.
How many stars does kolodny/immutability-helper have?
kolodny/immutability-helper has 5.2k GitHub stars — refresh the page for the live number, or check github.com/kolodny/immutability-helper. TopGit mirrors GitHub's count but does not claim minute-by-minute accuracy.
Is kolodny/immutability-helper open source?
Yes — kolodny/immutability-helper ships under the MIT license, which makes its source code freely readable (and, depending on license terms, forkable and reusable). Source: github.com/kolodny/immutability-helper.
What is kolodny/immutability-helper?
kolodny/immutability-helper (kolodny/immutability-helper) is a TypeScript project on GitHub. From the project's own README: mutate a copy of data without changing the original source
Where do I read more about kolodny/immutability-helper?
This TopGit page is a snapshot — the READ ME tab shows the project's own README content (links stripped, images preserved). The GitHub repository at github.com/kolodny/immutability-helper is the definitive source.
Read full README in the tab above.
Is immutability-helper worth your time?
ChatGPT, Claude and Perplexity can all read this page. Ask one of them what it makes of immutability-helper.