0
# Nested Operations
1
2
Methods for working with nested data structures using path-based access patterns. These operations work on both objects and arrays using array paths to specify nested locations.
3
4
## Capabilities
5
6
### setIn
7
8
Sets a nested property using a path array, creating intermediate objects/arrays as needed.
9
10
```javascript { .api }
11
/**
12
* Set nested property using path array
13
* @param {Object|Array} obj - Target object or array
14
* @param {Array} path - Array of keys/indices representing the path to the nested property
15
* @param {*} value - Value to set at the nested location
16
* @param {Object} [config] - Configuration options
17
* @param {boolean} [config.deep] - Deep merge if setting an object value
18
* @returns {Object|Array} New immutable structure with nested property set
19
*/
20
function setIn(obj, path, value, config);
21
```
22
23
**Usage Examples:**
24
25
```javascript
26
const Immutable = require("seamless-immutable");
27
28
// Setting in nested objects
29
const obj = Immutable({type: {main: "parrot", sub: "Norwegian Blue"}, status: "alive"});
30
const updated = obj.setIn(["type", "sub"], "Norwegian Ridgeback");
31
// Result: {type: {main: "parrot", sub: "Norwegian Ridgeback"}, status: "alive"}
32
33
// Setting in nested arrays
34
const arr = Immutable([[1, 2], [3, 4]]);
35
const updatedArr = arr.setIn([1, 0], 99);
36
// Result: [[1, 2], [99, 4]]
37
38
// Creating intermediate structures
39
const empty = Immutable({});
40
const nested = empty.setIn(["user", "profile", "name"], "Alice");
41
// Result: {user: {profile: {name: "Alice"}}}
42
43
// Mixed object/array paths
44
const complex = Immutable({users: [{name: "Alice"}, {name: "Bob"}]});
45
const updatedComplex = complex.setIn(["users", 0, "age"], 30);
46
// Result: {users: [{name: "Alice", age: 30}, {name: "Bob"}]}
47
48
// Deep merge when setting objects
49
const deepObj = Immutable({user: {name: "Alice", settings: {theme: "dark"}}});
50
const merged = deepObj.setIn(["user"], {age: 30}, {deep: true});
51
// Result: {user: {name: "Alice", age: 30, settings: {theme: "dark"}}}
52
```
53
54
### getIn
55
56
Gets a nested property value using a path array, with optional default value.
57
58
```javascript { .api }
59
/**
60
* Get nested property using path array
61
* @param {Object|Array} obj - Target object or array
62
* @param {Array} path - Array of keys/indices representing the path to the nested property
63
* @param {*} [defaultValue] - Default value returned if path is not found
64
* @returns {*} Value at the specified path, or defaultValue if not found
65
*/
66
function getIn(obj, path, defaultValue);
67
```
68
69
**Usage Examples:**
70
71
```javascript
72
const Immutable = require("seamless-immutable");
73
74
const obj = Immutable({
75
type: {main: "parrot", subtype: "Norwegian Blue"},
76
status: "alive",
77
users: [{name: "Alice", age: 30}, {name: "Bob", age: 25}]
78
});
79
80
// Get nested object property
81
const subtype = obj.getIn(["type", "subtype"]);
82
// Result: "Norwegian Blue"
83
84
// Get from nested array
85
const firstUserName = obj.getIn(["users", 0, "name"]);
86
// Result: "Alice"
87
88
// Path not found - returns undefined
89
const missing = obj.getIn(["type", "missing"]);
90
// Result: undefined
91
92
// Path not found with default value
93
const withDefault = obj.getIn(["type", "class"], "Aves");
94
// Result: "Aves"
95
96
// Deeply nested path
97
const deepNested = Immutable({a: {b: {c: {d: "found"}}}});
98
const value = deepNested.getIn(["a", "b", "c", "d"]);
99
// Result: "found"
100
101
// Array indices in path
102
const matrix = Immutable([[1, 2, 3], [4, 5, 6]]);
103
const element = matrix.getIn([1, 2]);
104
// Result: 6
105
```
106
107
### updateIn
108
109
Updates a nested property using an updater function and path array.
110
111
```javascript { .api }
112
/**
113
* Update nested property using updater function and path array
114
* @param {Object|Array} obj - Target object or array
115
* @param {Array} path - Array of keys/indices representing the path to the nested property
116
* @param {Function} updater - Function that receives current value and returns new value
117
* @param {...*} [args] - Additional arguments passed to the updater function
118
* @returns {Object|Array} New immutable structure with updated nested property
119
*/
120
function updateIn(obj, path, updater, ...args);
121
```
122
123
**Usage Examples:**
124
125
```javascript
126
const Immutable = require("seamless-immutable");
127
128
// Simple numeric update
129
function add(x, y) { return x + y; }
130
const obj = Immutable({foo: {bar: 1}});
131
const incremented = obj.updateIn(["foo", "bar"], add, 10);
132
// Result: {foo: {bar: 11}}
133
134
// String manipulation
135
const user = Immutable({profile: {name: "alice"}});
136
const capitalized = user.updateIn(["profile", "name"], name => name.toUpperCase());
137
// Result: {profile: {name: "ALICE"}}
138
139
// Array manipulation
140
const data = Immutable({items: {list: [1, 2, 3]}});
141
const withNewItem = data.updateIn(["items", "list"], list => list.concat(4));
142
// Result: {items: {list: [1, 2, 3, 4]}}
143
144
// Complex nested structure
145
const state = Immutable({
146
users: [
147
{id: 1, name: "Alice", scores: [10, 20]},
148
{id: 2, name: "Bob", scores: [15, 25]}
149
]
150
});
151
152
// Update nested array element
153
const updatedScores = state.updateIn(["users", 0, "scores"], scores =>
154
scores.map(score => score * 2)
155
);
156
// Result: users[0].scores becomes [20, 40]
157
158
// Update with multiple arguments
159
function multiply(current, factor, bonus) {
160
return current * factor + bonus;
161
}
162
const calculated = obj.updateIn(["foo", "bar"], multiply, 3, 5);
163
// Result: {foo: {bar: 8}} (1 * 3 + 5)
164
```
165
166
### update (Single-level)
167
168
Updates a property at the current level using an updater function.
169
170
```javascript { .api }
171
/**
172
* Update a property using an updater function
173
* @param {Object|Array} obj - Target object or array
174
* @param {string|number} property - Property key or array index to update
175
* @param {Function} updater - Function that receives current value and returns new value
176
* @param {...*} [args] - Additional arguments passed to the updater function
177
* @returns {Object|Array} New immutable structure with updated property
178
*/
179
function update(obj, property, updater, ...args);
180
```
181
182
**Usage Examples:**
183
184
```javascript
185
const Immutable = require("seamless-immutable");
186
187
// Object property update
188
function inc(x) { return x + 1; }
189
const obj = Immutable({foo: 1, bar: 2});
190
const incremented = obj.update("foo", inc);
191
// Result: {foo: 2, bar: 2}
192
193
// Array element update
194
const arr = Immutable([10, 20, 30]);
195
const doubled = arr.update(1, x => x * 2);
196
// Result: [10, 40, 30]
197
198
// Update with additional arguments
199
function add(current, amount) { return current + amount; }
200
const added = obj.update("foo", add, 5);
201
// Result: {foo: 6, bar: 2}
202
203
// Conditional updates
204
const conditionalUpdate = obj.update("foo", (current, threshold) =>
205
current > threshold ? current * 2 : current
206
, 0.5);
207
```
208
209
## Path Resolution
210
211
### Automatic Structure Creation
212
213
When using `setIn`, intermediate structures are automatically created based on the next key in the path:
214
215
```javascript
216
const Immutable = require("seamless-immutable");
217
218
const empty = Immutable({});
219
220
// Creates nested objects
221
const result1 = empty.setIn(["a", "b", "c"], "value");
222
// Result: {a: {b: {c: "value"}}}
223
224
// Creates array when next key is numeric
225
const result2 = empty.setIn(["users", 0, "name"], "Alice");
226
// Result: {users: [{name: "Alice"}]}
227
228
// Mixed creation
229
const result3 = empty.setIn(["data", 0, "items", "first"], "value");
230
// Result: {data: [{items: {first: "value"}}]}
231
```
232
233
### Path Validation
234
235
Paths must be arrays with at least one element:
236
237
```javascript
238
const obj = Immutable({a: 1});
239
240
// Valid paths
241
obj.setIn(["a"], 2); // ✓
242
obj.setIn(["b", "c"], 3); // ✓
243
obj.setIn([0, "name"], "test"); // ✓
244
245
// Invalid paths - throw TypeError
246
obj.setIn([], "value"); // ✗ Empty path
247
obj.setIn("a", "value"); // ✗ Not an array
248
obj.setIn(null, "value"); // ✗ Null path
249
```
250
251
### Working with Mixed Structures
252
253
Nested operations handle complex data structures with mixed objects and arrays:
254
255
```javascript
256
const Immutable = require("seamless-immutable");
257
258
const complexData = Immutable({
259
users: [
260
{
261
id: 1,
262
profile: {
263
name: "Alice",
264
addresses: [
265
{type: "home", city: "NYC"},
266
{type: "work", city: "SF"}
267
]
268
}
269
}
270
],
271
settings: {
272
theme: "dark",
273
features: ["feature1", "feature2"]
274
}
275
});
276
277
// Deep nested update
278
const updated = complexData.updateIn(
279
["users", 0, "profile", "addresses", 0, "city"],
280
city => city.toUpperCase()
281
);
282
283
// Get deep nested value
284
const workCity = complexData.getIn(["users", 0, "profile", "addresses", 1, "city"]);
285
286
// Set deep nested value
287
const withNewFeature = complexData.setIn(
288
["settings", "features", 2],
289
"feature3"
290
);
291
```
292
293
## Instance vs Static Methods
294
295
All nested operation methods are available in both instance and static forms:
296
297
```javascript
298
const Immutable = require("seamless-immutable");
299
const obj = Immutable({user: {name: "Alice"}});
300
301
// Instance methods (default API)
302
const set1 = obj.setIn(["user", "age"], 30);
303
const get1 = obj.getIn(["user", "name"]);
304
const updated1 = obj.updateIn(["user", "name"], name => name.toUpperCase());
305
306
// Static methods (static API)
307
const ImmutableS = require("seamless-immutable").static;
308
const set2 = ImmutableS.setIn(obj, ["user", "age"], 30);
309
const get2 = ImmutableS.getIn(obj, ["user", "name"]);
310
const updated2 = ImmutableS.updateIn(obj, ["user", "name"], name => name.toUpperCase());
311
```
312
313
The static API is recommended when you want to avoid method name pollution or work with a consistent functional programming style.