Package Exports
- @thi.ng/paths
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (@thi.ng/paths) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
@thi.ng/paths
About
This library provides immutable, optimized path-based accessors for vanilla JS objects.
Installation
yarn add @thi.ng/paths
Usage
import * as paths from "@thi.ng/paths";
The getter()
and setter()
functions transform a path like a.b.c
into a function operating directly at the value the path points to in
nested object. For getters, this essentially compiles to val = obj.a.b.c
, with the important difference that the function returns
undefined
if any intermediate values along the lookup path are
undefined (and doesn't throw an error).
The resulting setter function too accepts a single object to operate on and when called, immutably replaces the value at the given path, i.e. it produces a selective deep copy of obj up until given path. If any intermediate key is not present in the given object, it creates a plain empty object for that missing key and descends further along the path.
s = setter("a.b.c");
// or
s = setter(["a","b","c"]);
s({a: {b: {c: 23}}}, 24)
// {a: {b: {c: 24}}}
s({x: 23}, 24)
// { x: 23, a: { b: { c: 24 } } }
s(null, 24)
// { a: { b: { c: 24 } } }
In addition to these higher-order functions, the module also provides
immediate-use wrappers: getIn()
, setIn()
, updateIn()
and
deleteIn()
. These functions are using getter
/ setter
internally,
so have same behaviors.
state = {a: {b: {c: 23}}};
getIn(state, "a.b.c")
// 23
setIn(state, "a.b.c", 24)
// {a: {b: {c: 24}}}
// apply given function to path value
updateIn(state, "a.b.c", x => x + 1)
// {a: {b: {c: 24}}}
// immutably remove path key
deleteIn(state, "a.b.c.")
// {a: {b: {}}}
Only keys in the path will be updated, all other keys present in the given object retain their original/identical values to provide efficient structural sharing / re-use. This is the same behavior as in Clojure's immutable maps or those provided by ImmutableJS (albeit those implementation are completely different - they're using trees, we're using the ES6 spread op and recursive functional composition to produce the setter/updater).
s = setter("a.b.c");
// original
a = { x: { y: { z: 1 } }, u: { v: 2 } };
// updated version
b = s(a, 3);
// { x: { y: { z: 1 } }, u: { v: 2 }, a: { b: { c: 3 } } }
// verify anything under keys `x` & `u` is still identical
a.x === b.x // true
a.x.y === b.x.y // true
a.u === b.u; // true
Authors
- Karsten Schmidt
License
© 2016 - 2018 Karsten Schmidt // Apache Software License 2.0