objwalk 1.7.0 → 1.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +26 -10
- package/SPEC.md +74 -15
- package/dist/index.cjs +24 -8
- package/dist/index.d.cts +18 -3
- package/dist/index.d.ts +18 -3
- package/dist/index.js +24 -8
- package/package.json +1 -1
- package/skills/objwalk/SKILL.md +25 -4
package/README.md
CHANGED
|
@@ -125,21 +125,37 @@ Return `false` to stop the entire walk. For more control, `each` also accepts
|
|
|
125
125
|
`root` and `descend` options and provides literal path segments as a fourth
|
|
126
126
|
callback argument. [Traversal details](SPEC.md#each).
|
|
127
127
|
|
|
128
|
-
Use `map`
|
|
128
|
+
Use `map` to transform values while keeping the object and array structure:
|
|
129
129
|
|
|
130
130
|
```ts
|
|
131
|
-
import { map
|
|
131
|
+
import { map } from 'objwalk'
|
|
132
132
|
|
|
133
|
-
const cleaned = map({ name: ' Natalia ', tags: [' ts '] }, (_key, value
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
}
|
|
137
|
-
})
|
|
133
|
+
const cleaned = map({ name: ' Natalia ', tags: [' ts '] }, (_key, value) =>
|
|
134
|
+
typeof value === 'string' ? value.trim() : value
|
|
135
|
+
)
|
|
138
136
|
// { name: 'Natalia', tags: ['ts'] }
|
|
139
137
|
```
|
|
140
138
|
|
|
141
|
-
|
|
142
|
-
acyclic data
|
|
139
|
+
Each callback return becomes the value at that key or index in the new result.
|
|
140
|
+
The input is not modified by `map`. Both walkers expect acyclic data unless
|
|
141
|
+
traversal options prune the cycles.
|
|
142
|
+
|
|
143
|
+
When your callback handles each entry as a whole, use a shallow walk:
|
|
144
|
+
|
|
145
|
+
```ts
|
|
146
|
+
import { map } from 'objwalk'
|
|
147
|
+
|
|
148
|
+
const counts = map(
|
|
149
|
+
{ editors: ['Natalia'], readers: ['Ada', 'Grace'] },
|
|
150
|
+
(_key, value) => value.length,
|
|
151
|
+
{ shallow: true }
|
|
152
|
+
)
|
|
153
|
+
// { editors: 1, readers: 2 }
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
Shallow dictionary keys are typed as `string`; shallow array indexes are `number`.
|
|
157
|
+
For selective traversal, pass `descend` in the third argument.
|
|
158
|
+
[Mapping options](SPEC.md#map).
|
|
143
159
|
|
|
144
160
|
## Merge defaults or make a copy
|
|
145
161
|
|
|
@@ -188,7 +204,7 @@ formatting, and an `onError` callback are available through options.
|
|
|
188
204
|
| Delete one or several paths | [`flush(data, path)`](SPEC.md#flush) |
|
|
189
205
|
| Reshape data with a mapping | [`extract(source, mapping)`](SPEC.md#extract) |
|
|
190
206
|
| Visit nested values | [`each(data, callback, options?)`](SPEC.md#each) |
|
|
191
|
-
|
|
|
207
|
+
| Transform values while keeping keys | [`map(data, callback, options?)`](SPEC.md#map) |
|
|
192
208
|
| Merge plain objects | [`merge(target, ...sources)`](SPEC.md#merge) |
|
|
193
209
|
| Copy supported values | [`clone(value)`](SPEC.md#clone) |
|
|
194
210
|
| Compare values or selected paths | [`equally(a, b, paths?)`](SPEC.md#equally) |
|
package/SPEC.md
CHANGED
|
@@ -30,7 +30,7 @@ type DiffOperation =
|
|
|
30
30
|
| `flush(data, path)` | Input object | Mutates the input |
|
|
31
31
|
| `extract(source, mapping)` | New result object | Selected values are not cloned |
|
|
32
32
|
| `each(data, callback, options?)` | `undefined` | Passes original values to callbacks |
|
|
33
|
-
| `map(data, callback,
|
|
33
|
+
| `map(data, callback, options?)` | New array or dictionary | Callback returns each replacement value; pruned and returned values can retain references |
|
|
34
34
|
| `merge(target, ...sources)` | Target object | Mutates the target; replacement values are not cloned |
|
|
35
35
|
| `clone(value)` | Value of the same declared generic type | Recursively copies supported objects and arrays |
|
|
36
36
|
| `equally(a, b, paths?)` | `boolean` | Does not assign to the inputs |
|
|
@@ -41,8 +41,8 @@ type DiffOperation =
|
|
|
41
41
|
`pick`, `set`, and `flush` use `{}` when their `data` argument is `undefined`.
|
|
42
42
|
`set` and `flush` still require the path argument. `pick` defaults its path to `''`.
|
|
43
43
|
Their declared data contract is `ObjwalkObject`; this is not a guarantee that all
|
|
44
|
-
functions accept every possible JavaScript value. `each`
|
|
45
|
-
`clone` is generic; `equally`, `diff`, `parse`, and `stringify` accept `unknown` inputs.
|
|
44
|
+
functions accept every possible JavaScript value. `each` accepts `any`; `map`
|
|
45
|
+
accepts dictionaries and readonly arrays; `clone` is generic; `equally`, `diff`, `parse`, and `stringify` accept `unknown` inputs.
|
|
46
46
|
`extract` requires an object and a mapping; `merge` requires an object target.
|
|
47
47
|
|
|
48
48
|
Except for the documented JSON error handling, exceptions from callbacks, getters,
|
|
@@ -217,22 +217,81 @@ not share stop state.
|
|
|
217
217
|
## map
|
|
218
218
|
|
|
219
219
|
```ts
|
|
220
|
-
type MapCallback<
|
|
221
|
-
key:
|
|
220
|
+
type MapCallback<TResult = unknown, TKey extends WalkKey = WalkKey> = (
|
|
221
|
+
key: TKey,
|
|
222
222
|
value: any,
|
|
223
|
-
store: TStore,
|
|
224
223
|
path: string
|
|
225
|
-
) =>
|
|
226
|
-
```
|
|
224
|
+
) => TResult
|
|
227
225
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
226
|
+
type MapOptions = {
|
|
227
|
+
descend?: EachOptions['descend']
|
|
228
|
+
shallow?: boolean
|
|
229
|
+
}
|
|
230
|
+
```
|
|
232
231
|
|
|
233
|
-
|
|
234
|
-
root
|
|
235
|
-
|
|
232
|
+
`map(data, callback, options?)` transforms a dictionary or array without assigning
|
|
233
|
+
into the input. An array root produces a new array; a dictionary root produces a
|
|
234
|
+
new ordinary object. The root is excluded from callback visits. Every visited
|
|
235
|
+
property or array index retains its literal key; its value becomes the callback's
|
|
236
|
+
return value. `false`, `null`, and `undefined` are stored as ordinary results;
|
|
237
|
+
there is no callback return value for stopping, filtering, or deleting entries.
|
|
238
|
+
Callback replacements are not traversed again, including returned objects and arrays.
|
|
239
|
+
|
|
240
|
+
The callback receives `(key, value, path)`. Object keys are strings, array indexes
|
|
241
|
+
are numbers, and paths follow `each`'s descriptive string format. No accumulator or
|
|
242
|
+
store argument exists. `MapCallback`'s first generic argument is the return value
|
|
243
|
+
rather than the former store type; the optional second argument is the key type.
|
|
244
|
+
Array results are typed as `TResult[]`; dictionary results as
|
|
245
|
+
`Record<string, TResult>`. A dictionary-or-array union input produces the matching
|
|
246
|
+
union result type. Readonly input arrays are accepted and produce mutable new arrays.
|
|
247
|
+
Deep callback values are typed as `any`, since earlier child transformations can
|
|
248
|
+
change their contents.
|
|
249
|
+
|
|
250
|
+
Deep traversal is the default. Plain objects and arrays are recursively mapped
|
|
251
|
+
before their containing value is passed to the callback. Thus callbacks run in
|
|
252
|
+
postorder: children first, then their parent, with the root still excluded.
|
|
253
|
+
A container callback receives a newly built container containing its already
|
|
254
|
+
mapped children. A pruned container callback instead receives the original value
|
|
255
|
+
by reference. `Date`, `RegExp`, other non-plain objects, and functions are leaves:
|
|
256
|
+
they are passed directly to the callback without rebuilding their internal state.
|
|
257
|
+
The root dictionary's own entries are enumerated regardless of its prototype;
|
|
258
|
+
the plain-object restriction applies to nested traversal.
|
|
259
|
+
|
|
260
|
+
Objects enumerate own enumerable string keys; inherited, symbol, and non-enumerable
|
|
261
|
+
properties are excluded. Literal dots, brackets, empty keys, and `__proto__` are
|
|
262
|
+
preserved as own data properties rather than parsed as paths. Result objects use
|
|
263
|
+
`Object.prototype`; source prototypes and descriptors are not copied. Array indexes
|
|
264
|
+
follow `each` iteration, preserving length and absent slots. An explicitly returned
|
|
265
|
+
`undefined` is an own slot, whereas an unvisited hole remains absent. Inherited
|
|
266
|
+
indexed values can be visited; extra array properties are excluded.
|
|
267
|
+
|
|
268
|
+
`descend` runs on each original traversable container before visiting children,
|
|
269
|
+
including the excluded root. It receives `EachEntry` with literal `segments`;
|
|
270
|
+
modifying these segments does not alter traversal paths. Returning `false` prunes
|
|
271
|
+
children, then the container's callback processes the original value as a whole.
|
|
272
|
+
Pruning the root produces an empty container of the same kind, with no callback
|
|
273
|
+
visits. This timing differs from `each`, which calls its callback before `descend`.
|
|
274
|
+
|
|
275
|
+
`shallow` defaults to `false`. With literal `shallow: true`, only immediate root
|
|
276
|
+
children are mapped: dictionary callback keys are typed as `string`, and statically
|
|
277
|
+
known array keys as `number`. Deep calls, dynamic shallow flags, and union inputs
|
|
278
|
+
keep `WalkKey`. An arbitrary `descend` predicate does not narrow keys. When both
|
|
279
|
+
options are present, `descend` is evaluated only for the root, because child
|
|
280
|
+
containers are already at the shallow limit.
|
|
281
|
+
|
|
282
|
+
Traversed containers are new. Pruned containers, special objects, and values
|
|
283
|
+
returned by the callback may share references with the input. Each occurrence of
|
|
284
|
+
a shared traversable container is mapped separately. Cycles are not detected;
|
|
285
|
+
pruning can prevent descent into a cyclic branch. Exceptions from callbacks,
|
|
286
|
+
getters, and `descend` propagate. The function does not roll back callback side
|
|
287
|
+
effects or await promises returned by callbacks.
|
|
288
|
+
|
|
289
|
+
This replaces the published accumulator-based contract. Migrate
|
|
290
|
+
`map(data, (key, value, store, path) => { store[key] = transform(value) }, store)`
|
|
291
|
+
to `map(data, (key, value, path) => transform(value), options)` when the result
|
|
292
|
+
retains input keys. Callers that build a different structure should use `each`
|
|
293
|
+
and manage their accumulator explicitly. Old stores are not accepted as options,
|
|
294
|
+
and there is no compatibility overload or `undefined` placeholder.
|
|
236
295
|
|
|
237
296
|
## merge
|
|
238
297
|
|
package/dist/index.cjs
CHANGED
|
@@ -225,14 +225,6 @@ var extract = (source, mapping) => {
|
|
|
225
225
|
return result;
|
|
226
226
|
};
|
|
227
227
|
|
|
228
|
-
// src/map.ts
|
|
229
|
-
var map = (data, callback, store = {}) => {
|
|
230
|
-
each(data, (key, value, path) => {
|
|
231
|
-
callback(key, value, store, path);
|
|
232
|
-
});
|
|
233
|
-
return store;
|
|
234
|
-
};
|
|
235
|
-
|
|
236
228
|
// src/helpers/isPlainObject.ts
|
|
237
229
|
var isPlainObject = (value) => {
|
|
238
230
|
if (value !== null && typeof value === "object") {
|
|
@@ -242,6 +234,30 @@ var isPlainObject = (value) => {
|
|
|
242
234
|
return false;
|
|
243
235
|
};
|
|
244
236
|
|
|
237
|
+
// src/map.ts
|
|
238
|
+
var map = (data, callback, { descend, shallow = false } = {}) => {
|
|
239
|
+
const walk = (value, key, path, segments) => {
|
|
240
|
+
const root = key === void 0;
|
|
241
|
+
let mapped = root ? Array.isArray(value) ? [] : {} : value;
|
|
242
|
+
if ((root || Array.isArray(value) || isPlainObject(value)) && (root || shallow === false) && (descend === void 0 || descend({ key, value, path, segments: [...segments] }))) {
|
|
243
|
+
mapped = Array.isArray(value) ? Array(value.length) : {};
|
|
244
|
+
each(value, (key2, value2) => {
|
|
245
|
+
const childPath = createPath(path, key2, Array.isArray(mapped));
|
|
246
|
+
const childSegments = [...segments, key2];
|
|
247
|
+
const result = walk(value2, key2, childPath, childSegments);
|
|
248
|
+
Object.defineProperty(mapped, key2, {
|
|
249
|
+
value: result,
|
|
250
|
+
writable: true,
|
|
251
|
+
enumerable: true,
|
|
252
|
+
configurable: true
|
|
253
|
+
});
|
|
254
|
+
}, { descend: ({ segments: segments2 }) => segments2.length === 0 });
|
|
255
|
+
}
|
|
256
|
+
return key !== void 0 ? callback(key, mapped, path) : mapped;
|
|
257
|
+
};
|
|
258
|
+
return walk(data, void 0, "", []);
|
|
259
|
+
};
|
|
260
|
+
|
|
245
261
|
// src/merge.ts
|
|
246
262
|
var unsafeKeys = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
|
|
247
263
|
var merge = (target, ...sources) => {
|
package/dist/index.d.cts
CHANGED
|
@@ -48,8 +48,23 @@ declare const pick: (data?: ObjwalkObject$1, path?: string, options?: PickOption
|
|
|
48
48
|
type ExtractMapping = Record<string, string | string[]>;
|
|
49
49
|
declare const extract: (source: ObjwalkObject$1, mapping: ExtractMapping) => ObjwalkObject$1;
|
|
50
50
|
|
|
51
|
-
type MapCallback<
|
|
52
|
-
|
|
51
|
+
type MapCallback<TResult = unknown, TKey extends WalkKey = WalkKey> = (key: TKey, value: any, path: string) => TResult;
|
|
52
|
+
type MapOptions = {
|
|
53
|
+
descend?: EachOptions['descend'];
|
|
54
|
+
shallow?: boolean;
|
|
55
|
+
};
|
|
56
|
+
type Map = {
|
|
57
|
+
<TResult>(data: readonly unknown[], callback: MapCallback<TResult, number>, options: MapOptions & {
|
|
58
|
+
shallow: true;
|
|
59
|
+
}): TResult[];
|
|
60
|
+
<TResult>(data: Record<string, unknown>, callback: MapCallback<TResult, string>, options: MapOptions & {
|
|
61
|
+
shallow: true;
|
|
62
|
+
}): Record<string, TResult>;
|
|
63
|
+
<TResult>(data: readonly unknown[], callback: MapCallback<TResult>, options?: MapOptions): TResult[];
|
|
64
|
+
<TResult>(data: Record<string, unknown>, callback: MapCallback<TResult>, options?: MapOptions): Record<string, TResult>;
|
|
65
|
+
<TResult>(data: Record<string, unknown> | readonly unknown[], callback: MapCallback<TResult>, options?: MapOptions): Record<string, TResult> | TResult[];
|
|
66
|
+
};
|
|
67
|
+
declare const map: Map;
|
|
53
68
|
|
|
54
69
|
declare const merge: <T extends ObjwalkObject$1>(target: T, ...sources: unknown[]) => T;
|
|
55
70
|
|
|
@@ -68,4 +83,4 @@ declare const parse: (raw: unknown, { fallback, onError, reviver }?: ParseOption
|
|
|
68
83
|
|
|
69
84
|
declare const stringify: (value: unknown, { fallback, onError, replacer, space }?: StringifyOptions) => string | undefined;
|
|
70
85
|
|
|
71
|
-
export { type DiffOperation, type EachCallback, type EachEntry, type EachOptions, type ExtractMapping, type MapCallback, type ObjwalkObject$1 as ObjwalkObject, type ParseOptions, type PickOptions, type StringifyOptions, type WalkKey, clone, diff, each, equally, extract, flush, map, merge, parse, pick, set, stringify };
|
|
86
|
+
export { type DiffOperation, type EachCallback, type EachEntry, type EachOptions, type ExtractMapping, type MapCallback, type MapOptions, type ObjwalkObject$1 as ObjwalkObject, type ParseOptions, type PickOptions, type StringifyOptions, type WalkKey, clone, diff, each, equally, extract, flush, map, merge, parse, pick, set, stringify };
|
package/dist/index.d.ts
CHANGED
|
@@ -48,8 +48,23 @@ declare const pick: (data?: ObjwalkObject$1, path?: string, options?: PickOption
|
|
|
48
48
|
type ExtractMapping = Record<string, string | string[]>;
|
|
49
49
|
declare const extract: (source: ObjwalkObject$1, mapping: ExtractMapping) => ObjwalkObject$1;
|
|
50
50
|
|
|
51
|
-
type MapCallback<
|
|
52
|
-
|
|
51
|
+
type MapCallback<TResult = unknown, TKey extends WalkKey = WalkKey> = (key: TKey, value: any, path: string) => TResult;
|
|
52
|
+
type MapOptions = {
|
|
53
|
+
descend?: EachOptions['descend'];
|
|
54
|
+
shallow?: boolean;
|
|
55
|
+
};
|
|
56
|
+
type Map = {
|
|
57
|
+
<TResult>(data: readonly unknown[], callback: MapCallback<TResult, number>, options: MapOptions & {
|
|
58
|
+
shallow: true;
|
|
59
|
+
}): TResult[];
|
|
60
|
+
<TResult>(data: Record<string, unknown>, callback: MapCallback<TResult, string>, options: MapOptions & {
|
|
61
|
+
shallow: true;
|
|
62
|
+
}): Record<string, TResult>;
|
|
63
|
+
<TResult>(data: readonly unknown[], callback: MapCallback<TResult>, options?: MapOptions): TResult[];
|
|
64
|
+
<TResult>(data: Record<string, unknown>, callback: MapCallback<TResult>, options?: MapOptions): Record<string, TResult>;
|
|
65
|
+
<TResult>(data: Record<string, unknown> | readonly unknown[], callback: MapCallback<TResult>, options?: MapOptions): Record<string, TResult> | TResult[];
|
|
66
|
+
};
|
|
67
|
+
declare const map: Map;
|
|
53
68
|
|
|
54
69
|
declare const merge: <T extends ObjwalkObject$1>(target: T, ...sources: unknown[]) => T;
|
|
55
70
|
|
|
@@ -68,4 +83,4 @@ declare const parse: (raw: unknown, { fallback, onError, reviver }?: ParseOption
|
|
|
68
83
|
|
|
69
84
|
declare const stringify: (value: unknown, { fallback, onError, replacer, space }?: StringifyOptions) => string | undefined;
|
|
70
85
|
|
|
71
|
-
export { type DiffOperation, type EachCallback, type EachEntry, type EachOptions, type ExtractMapping, type MapCallback, type ObjwalkObject$1 as ObjwalkObject, type ParseOptions, type PickOptions, type StringifyOptions, type WalkKey, clone, diff, each, equally, extract, flush, map, merge, parse, pick, set, stringify };
|
|
86
|
+
export { type DiffOperation, type EachCallback, type EachEntry, type EachOptions, type ExtractMapping, type MapCallback, type MapOptions, type ObjwalkObject$1 as ObjwalkObject, type ParseOptions, type PickOptions, type StringifyOptions, type WalkKey, clone, diff, each, equally, extract, flush, map, merge, parse, pick, set, stringify };
|
package/dist/index.js
CHANGED
|
@@ -188,14 +188,6 @@ var extract = (source, mapping) => {
|
|
|
188
188
|
return result;
|
|
189
189
|
};
|
|
190
190
|
|
|
191
|
-
// src/map.ts
|
|
192
|
-
var map = (data, callback, store = {}) => {
|
|
193
|
-
each(data, (key, value, path) => {
|
|
194
|
-
callback(key, value, store, path);
|
|
195
|
-
});
|
|
196
|
-
return store;
|
|
197
|
-
};
|
|
198
|
-
|
|
199
191
|
// src/helpers/isPlainObject.ts
|
|
200
192
|
var isPlainObject = (value) => {
|
|
201
193
|
if (value !== null && typeof value === "object") {
|
|
@@ -205,6 +197,30 @@ var isPlainObject = (value) => {
|
|
|
205
197
|
return false;
|
|
206
198
|
};
|
|
207
199
|
|
|
200
|
+
// src/map.ts
|
|
201
|
+
var map = (data, callback, { descend, shallow = false } = {}) => {
|
|
202
|
+
const walk = (value, key, path, segments) => {
|
|
203
|
+
const root = key === void 0;
|
|
204
|
+
let mapped = root ? Array.isArray(value) ? [] : {} : value;
|
|
205
|
+
if ((root || Array.isArray(value) || isPlainObject(value)) && (root || shallow === false) && (descend === void 0 || descend({ key, value, path, segments: [...segments] }))) {
|
|
206
|
+
mapped = Array.isArray(value) ? Array(value.length) : {};
|
|
207
|
+
each(value, (key2, value2) => {
|
|
208
|
+
const childPath = createPath(path, key2, Array.isArray(mapped));
|
|
209
|
+
const childSegments = [...segments, key2];
|
|
210
|
+
const result = walk(value2, key2, childPath, childSegments);
|
|
211
|
+
Object.defineProperty(mapped, key2, {
|
|
212
|
+
value: result,
|
|
213
|
+
writable: true,
|
|
214
|
+
enumerable: true,
|
|
215
|
+
configurable: true
|
|
216
|
+
});
|
|
217
|
+
}, { descend: ({ segments: segments2 }) => segments2.length === 0 });
|
|
218
|
+
}
|
|
219
|
+
return key !== void 0 ? callback(key, mapped, path) : mapped;
|
|
220
|
+
};
|
|
221
|
+
return walk(data, void 0, "", []);
|
|
222
|
+
};
|
|
223
|
+
|
|
208
224
|
// src/merge.ts
|
|
209
225
|
var unsafeKeys = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
|
|
210
226
|
var merge = (target, ...sources) => {
|
package/package.json
CHANGED
package/skills/objwalk/SKILL.md
CHANGED
|
@@ -31,7 +31,7 @@ import { clone, diff, each, equally, extract, flush, map, merge, parse, pick, se
|
|
|
31
31
|
| Delete nested properties | `flush(data, path)`; accepts one path or `string[]`, deletes own properties, mutates and returns `data`; missing paths are left unchanged. |
|
|
32
32
|
| Reshape an object | `extract(source, mapping)`; mapping keys are destination paths, values are source paths. |
|
|
33
33
|
| Visit nested values | `each(data, (key, value, path, segments) => { ... }, options?)`; supports objects and arrays, root is excluded by default; returning `false` stops the entire traversal. |
|
|
34
|
-
|
|
|
34
|
+
| Transform nested values | `map(data, (key, value, path) => replacement, options?)`; returns a new array or dictionary with the same keys. |
|
|
35
35
|
| Deep merge | `merge(target, ...sources)`; mutates and returns the target, merges plain objects, replaces arrays and non-plain values. |
|
|
36
36
|
| Deep copy | `clone(value)`; preserves `Date`, `RegExp`, symbol keys, and circular references. |
|
|
37
37
|
| Deep comparison | `equally(a, b, paths?)`; supports `NaN`, `Date`, `RegExp`, and circular references; optional `string[]` compares only selected paths. |
|
|
@@ -108,11 +108,32 @@ the entire traversal, including siblings and ancestor branches; other return val
|
|
|
108
108
|
are ignored. The stopped container's `descend` is not called, and its children and
|
|
109
109
|
subsequent values are not read. Object keys are collected on entering a container;
|
|
110
110
|
values are read as visited. `each` still returns `undefined`. Existing callbacks
|
|
111
|
-
that returned `false` must omit that return to keep walking.
|
|
112
|
-
|
|
113
|
-
Mutating received segments does not affect traversal. Callback/getter/descend errors
|
|
111
|
+
that returned `false` must omit that return to keep walking. Mutating received
|
|
112
|
+
segments does not affect traversal. Callback/getter/descend errors
|
|
114
113
|
propagate. Cycles are not detected.
|
|
115
114
|
|
|
115
|
+
`map(data, callback, options?)` returns a new array for an array root and a new
|
|
116
|
+
ordinary dictionary for a dictionary root. Its callback is `(key, value, path)`;
|
|
117
|
+
return the replacement value. There is no store argument. `false`, `null`, and
|
|
118
|
+
`undefined` are ordinary output values, not traversal control. To accumulate a
|
|
119
|
+
different structure, use `each` with an explicit accumulator.
|
|
120
|
+
|
|
121
|
+
Deep map callbacks run children first, then their containing value; the root is
|
|
122
|
+
excluded. Plain objects and arrays are rebuilt, while non-plain objects such as
|
|
123
|
+
Date and RegExp are passed to the callback as leaves. Callback results are not
|
|
124
|
+
traversed again. Source data is not assigned to, but returned or pruned values
|
|
125
|
+
can retain references. Array holes and literal object keys are preserved.
|
|
126
|
+
|
|
127
|
+
`MapOptions` is the third argument. `descend` receives original containers before
|
|
128
|
+
children are mapped; false prunes their children and passes the original value to
|
|
129
|
+
the callback. It also runs for the excluded root, where false produces an empty
|
|
130
|
+
result of the same kind. Literal `shallow: true` visits only immediate children,
|
|
131
|
+
typing dictionary keys as `string` and array keys as `number`. When both options
|
|
132
|
+
are present, `descend` is evaluated only for the root. Deep/dynamic calls keep
|
|
133
|
+
`WalkKey`; a custom descend predicate alone cannot narrow keys.
|
|
134
|
+
`MapCallback<TResult, TKey>` describes the callback's returned value and key type.
|
|
135
|
+
This is a breaking replacement of the old store-based map, not an overload.
|
|
136
|
+
|
|
116
137
|
## Differences
|
|
117
138
|
|
|
118
139
|
`diff` recursively compares two plain objects by their own enumerable string keys;
|