|
@@ -261,6 +261,84 @@ an object will be treated as a `Map` (unlike the default string case,
|
|
|
where it is treated as an object), so copy wil be created
|
|
|
using `new Map(obj)`, not using `{...obj}`.
|
|
|
|
|
|
+### `deepCopyOnMap(key, ...)(fn)`
|
|
|
+### `decomap(key, ...)(fn)`
|
|
|
+
|
|
|
+Creates a modifier function allowing
|
|
|
+to "map" value at specified key
|
|
|
+in an immutable fashion, eg. creating a modified copy
|
|
|
+when actual modification happens.
|
|
|
+
|
|
|
+If properties that are to be parents of a sub-value
|
|
|
+are not present, they are _not_ created.
|
|
|
+In other words, if the key to modify does not exist,
|
|
|
+no change happens.
|
|
|
+
|
|
|
+Specify keys by passing a list of keys to `deepCopyOnMap`.
|
|
|
+Key can be either:
|
|
|
+ - number
|
|
|
+ - `keyInMap(obj)`
|
|
|
+ - array of Keys
|
|
|
+ - anything else, which is `toString()`ed and dot-split.
|
|
|
+
|
|
|
+In case no change actually happens (same value is set which is
|
|
|
+already present), returns the original object.
|
|
|
+
|
|
|
+```js
|
|
|
+const mapName = decomap("name");
|
|
|
+
|
|
|
+mapName(x => x.toUpperCase())({name: "Tom"});
|
|
|
+// => {name: "TOM"}
|
|
|
+
|
|
|
+const mapCity = decomap("address.city");
|
|
|
+const mapCity2 = decomap("address", "city");
|
|
|
+// and other forms, like:
|
|
|
+// const mapCity3 = decomap(["address", "city"]);
|
|
|
+// const mapCity4 = decomap("address", [[], "city"]);
|
|
|
+// const mapCity5 = decomap([[], "address.city"]);
|
|
|
+// etc.
|
|
|
+const object = {address: {city: "New York"}};
|
|
|
+
|
|
|
+mapCity(x => "London")(object);
|
|
|
+// => {address: {city: "London"}}
|
|
|
+mapCity2(x => "London")(object);
|
|
|
+// => {address: {city: "London"}}
|
|
|
+object;
|
|
|
+// => {address: {city: "New York"}}
|
|
|
+mapCity(x => "New York")(object) === object;
|
|
|
+// => true
|
|
|
+mapCity2(x => "New York")(object) === object;
|
|
|
+// => true
|
|
|
+
|
|
|
+const mapCityLondon = mapCity(x => "London");
|
|
|
+
|
|
|
+mapCityLondon(undefined);
|
|
|
+// => undefined
|
|
|
+mapCityLondon(null);
|
|
|
+// => null
|
|
|
+mapCityLondon({});
|
|
|
+// => {}
|
|
|
+mapCityLondon({address: null});
|
|
|
+// => {address: null}
|
|
|
+mapCityLondon({address: {}});
|
|
|
+// => {address: {}}
|
|
|
+mapCityLondon({address: {city: null}});
|
|
|
+// => {address: {city: "London"}}
|
|
|
+```
|
|
|
+
|
|
|
+If you put a number in a list of keys to use,
|
|
|
+an object will be treated as an array (unlike the default string case,
|
|
|
+where it is treated as an object), so copy wil be created
|
|
|
+using `[...obj]`, not using `{...obj}`.
|
|
|
+
|
|
|
+That way you can create eg. `const c = decomap("person", 34, "name")`
|
|
|
+to "set" `obj.person[34].name` with `c(fn)(obj)`.
|
|
|
+
|
|
|
+If you put a `keyInMap(key)` in a list of keys to use,
|
|
|
+an object will be treated as a `Map` (unlike the default string case,
|
|
|
+where it is treated as an object), so copy wil be created
|
|
|
+using `new Map(obj)`, not using `{...obj}`.
|
|
|
+
|
|
|
### `keyInMap(obj)`
|
|
|
### `kim(obj)`
|
|
|
|