ih v1.3.0
ih
Simple immutability helpers for javascript apps.
Purpose
Like using immutable data, but want to work with plain javascript objects? Use this small set of helpers to manipulate objects in an immutable way. Each method returns a new object, with the minimal set of changes required to complete the operation.
ih is well-tested, 1kb when minified and gzipped, and has no dependencies. It's based on tools we've built for our React/Redux frontend app at ClassDojo.
Usage
const ih = require("ih");
const obj = {
a: {
b: {
c: 4
}
},
arr: [
{id: 1},
{id: 2}
]
};
const get1 = ih.get(obj, "a.b.c") // => 4
const get2 = ih.get(obj, "a.b") // => {c: 4}
const set1 = ih.set(obj, "a", 3) // => new obj with a = 3.
const set2 = ih.set(obj, "a.b.c", 5) // => new obj with a.b.c = 5. obj.a and obj.a.b are both new objects.
const set3 = ih.set(obj, "arr.0", {id: 3}) // => new obj with arr[0] = {id: 3}. arr is a new array, second item is not.
const set4 = ih.set(obj, "a.e.f", 4) // throws - use setDeep for this.
const set4 = ih.setDeep(obj, "a.e.f", 4) // => new obj with a and a.e both objects, and a.e.f == 4.
const transformed = ih.transform(obj, "a.b.c", (x) => x - 1) // => new obj with a.b.c = 3.
const concatted = ih.concat(obj, "arr", [{id: 3}]) // => new obj with a new array with an extra item at arr.
const merged = ih.merge(obj, "a.b", {d: 3, e: 4}) // => new obj with a.b now having 3 keys.How it works
Under the hood, ih is essentially a wrapper around Object.assign, making usage of this funcationality much more readable. For example,
ih.set(obj, "a.b.c", 3)desugars to
Object.assign({}, obj, {
a: Object.assign({}, obj.a, {
b: Object.assign({}, obj.b, {
c: 3
});
});
});or, with ES7 spread syntax
{
...obj,
a: {
...obj.a,
b: {
...obj.b,
c: 3
}
}
}API
In all methods that follow, obj is the object to be operated on, and path is either a string or an array of strings representing the path within an object to be transformed.
Basic
get(obj, path)- returns the value atpathwithinobj.set(obj, path, val)- returns a copy ofobj, with the value atpathset toval.setDeep(obj, path, val)- likeset, but will recursively create objects to set a nested value.without(obj, path)- returns a copy of obj, with the key atpathremoved.
Transformations
transform(obj, path, fn)-gets the value atpath, callsfnon that value, andsets the path to the returned value.transformDeep(obj, path, fn)- liketransform, but usingsetDeep.merge(obj, [path,] val)- merges all properties of item atpathwith those inval. Values fromvaltake precedence. If only two arguments are provided, mergesvaldirectly withobj.mergeDeep(obj, path, val)- likemerge, but usingsetDeep.inc(obj, path, val = 1)- increments the value atpathbyval, or sets it tovalif it is null. Throws if it is a non-numerical value.incDeep(obj, path, val = 1)- likeinc, but usingsetDeep.toggle(obj, path)- applies thenotoperator to the value atpath.toggleDeep(obj, path, val = 1)- liketoggle, but usingsetDeep.
Array operations
concat(obj, path, val)- concatsvalto the end of the array atpath, or setspathtovalif there is nothing there. Throws if a non-array value is there.concatDeep(obj, path, val = 1)- likeconcat, but usingsetDeep.concatLeft(obj, path, val)- concatsvalto the beginning of the array atpath, or setspathtovalif there is nothing there. Throws if a non-array value is there.concatLeftDeep(obj, path, val = 1)- likeconcatLeft, but usingsetDeep.