@helpers4/object 2.0.0-alpha.9 → 2.0.0-beta.3
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 +21 -7
- package/lib/index.d.ts +255 -24
- package/lib/index.js +476 -84
- package/lib/index.js.map +1 -1
- package/llms.txt +804 -0
- package/meta/api.json +644 -65
- package/meta/category.json +6 -0
- package/meta/examples.json +141 -11
- package/meta/licenses.json +1 -8
- package/meta/native-alternatives.json +50 -0
- package/package.json +13 -6
package/llms.txt
ADDED
|
@@ -0,0 +1,804 @@
|
|
|
1
|
+
# @helpers4/object
|
|
2
|
+
|
|
3
|
+
> Tree-shakable TypeScript utility functions for the `object` domain.
|
|
4
|
+
> Package: `@helpers4/object` — Version: 2.0.0-beta.3
|
|
5
|
+
> License: LGPL-3.0-or-later
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```sh
|
|
10
|
+
npm install @helpers4/object
|
|
11
|
+
# or
|
|
12
|
+
pnpm add @helpers4/object
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Usage
|
|
16
|
+
|
|
17
|
+
```typescript
|
|
18
|
+
import { compact, deepClone, deepMerge, ... } from '@helpers4/object';
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Functions
|
|
22
|
+
|
|
23
|
+
| Function | Description |
|
|
24
|
+
|---|---|
|
|
25
|
+
| `compact` | Removes all entries with falsy values (`false`, `null`, `undefined`, `0`, `""`, `NaN`) from an objec |
|
|
26
|
+
| `deepClone` | Creates a deep copy of an object or array |
|
|
27
|
+
| `deepMerge` | Merges two or more objects deeply |
|
|
28
|
+
| `diff` | Structural object diff. Returns `true` when both inputs are deeply equal, otherwise a DiffResult de |
|
|
29
|
+
| `equalsDeep` | Recursive structural object equality. Boolean wrapper around diff \u2014 returns `true` when the tw |
|
|
30
|
+
| `equalsShallow` | One-level (shallow) object equality. Two objects are equal when they share the exact same set of ow |
|
|
31
|
+
| `get` | Gets a value from an object using a dot-notated path |
|
|
32
|
+
| `groupBy` | Groups an array of items by a key derived from each item. A thin, typed wrapper around `Object.grou |
|
|
33
|
+
| `invert` | Returns a new object with keys and values swapped. If multiple keys share the same value, the last o |
|
|
34
|
+
| `map` | Transforms the values and/or keys of a plain object in a single pass. Both callbacks are optional a |
|
|
35
|
+
| `omit` | Creates a new object without the specified keys. |
|
|
36
|
+
| `pick` | Creates a new object with only the specified keys. |
|
|
37
|
+
| `removeUndefinedNull` | Remove null and undefined values from an object. |
|
|
38
|
+
| `safeJsonParse` | Parses a JSON string, returning `null` (or a fallback) on any parse failure. Unlike `JSON.parse`, t |
|
|
39
|
+
| `set` | Sets a value in an object using a dot-notated path |
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## API Reference
|
|
44
|
+
|
|
45
|
+
### `compact`
|
|
46
|
+
|
|
47
|
+
Removes all entries with falsy values (`false`, `null`, `undefined`, `0`, `""`, `NaN`) from an object.
|
|
48
|
+
|
|
49
|
+
```typescript
|
|
50
|
+
import { compact } from '@helpers4/object';
|
|
51
|
+
|
|
52
|
+
compact<T extends Record<string, unknown>>(obj: T): Partial<T>
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
**Parameters:**
|
|
56
|
+
|
|
57
|
+
- `obj: T` — The source object
|
|
58
|
+
|
|
59
|
+
**Returns:** `Partial<T>` — A new object containing only entries with truthy values
|
|
60
|
+
|
|
61
|
+
```typescript
|
|
62
|
+
import { compact } from '@helpers4/object';
|
|
63
|
+
|
|
64
|
+
compact(obj: undefined): undefined
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
**Parameters:**
|
|
68
|
+
|
|
69
|
+
- `obj: undefined` — The source object
|
|
70
|
+
|
|
71
|
+
**Returns:** `undefined` — A new object containing only entries with truthy values
|
|
72
|
+
|
|
73
|
+
```typescript
|
|
74
|
+
import { compact } from '@helpers4/object';
|
|
75
|
+
|
|
76
|
+
compact(obj: null): null
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
**Parameters:**
|
|
80
|
+
|
|
81
|
+
- `obj: null` — The source object
|
|
82
|
+
|
|
83
|
+
**Returns:** `null` — A new object containing only entries with truthy values
|
|
84
|
+
|
|
85
|
+
**Examples:**
|
|
86
|
+
|
|
87
|
+
*Remove falsy values from object*
|
|
88
|
+
|
|
89
|
+
Removes all entries with falsy values (false, null, undefined, 0, "", NaN).
|
|
90
|
+
|
|
91
|
+
```typescript
|
|
92
|
+
compact({ a: 1, b: null, c: '', d: 0, e: 'hello' })
|
|
93
|
+
// => { a: 1, e: 'hello' }
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
*Clean up API response*
|
|
97
|
+
|
|
98
|
+
Useful to strip empty or missing fields before sending data.
|
|
99
|
+
|
|
100
|
+
```typescript
|
|
101
|
+
compact({ name: 'Alice', email: '', age: 0, role: 'admin' })
|
|
102
|
+
// => { name: 'Alice', role: 'admin' }
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
---
|
|
106
|
+
|
|
107
|
+
### `deepClone`
|
|
108
|
+
|
|
109
|
+
Creates a deep copy of an object or array
|
|
110
|
+
|
|
111
|
+
```typescript
|
|
112
|
+
import { deepClone } from '@helpers4/object';
|
|
113
|
+
|
|
114
|
+
deepClone<T>(obj: T): T
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
**Parameters:**
|
|
118
|
+
|
|
119
|
+
- `obj: T` — The object to clone
|
|
120
|
+
|
|
121
|
+
**Returns:** `T` — Deep cloned object
|
|
122
|
+
|
|
123
|
+
**Examples:**
|
|
124
|
+
|
|
125
|
+
*Clone a nested object*
|
|
126
|
+
|
|
127
|
+
Creates a deep copy — modifying the clone does not affect the original.
|
|
128
|
+
|
|
129
|
+
```typescript
|
|
130
|
+
const original = { a: { b: 1 } };
|
|
131
|
+
const cloned = deepClone(original);
|
|
132
|
+
cloned.a.b = 2;
|
|
133
|
+
// original.a.b is still 1
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
---
|
|
137
|
+
|
|
138
|
+
### `deepMerge`
|
|
139
|
+
|
|
140
|
+
Merges two or more objects deeply
|
|
141
|
+
|
|
142
|
+
```typescript
|
|
143
|
+
import { deepMerge } from '@helpers4/object';
|
|
144
|
+
|
|
145
|
+
deepMerge<T extends Record<string, unknown>>(target: T, sources: Record<string, unknown>[]): T
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
**Parameters:**
|
|
149
|
+
|
|
150
|
+
- `target: T` — The target object
|
|
151
|
+
- `sources: Record<string, unknown>[]` — The source objects to merge
|
|
152
|
+
|
|
153
|
+
**Returns:** `T` — The merged object
|
|
154
|
+
|
|
155
|
+
```typescript
|
|
156
|
+
import { deepMerge } from '@helpers4/object';
|
|
157
|
+
|
|
158
|
+
deepMerge(target: undefined, sources: Record<string, unknown>[]): undefined
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
**Parameters:**
|
|
162
|
+
|
|
163
|
+
- `target: undefined` — The target object
|
|
164
|
+
- `sources: Record<string, unknown>[]` — The source objects to merge
|
|
165
|
+
|
|
166
|
+
**Returns:** `undefined` — The merged object
|
|
167
|
+
|
|
168
|
+
```typescript
|
|
169
|
+
import { deepMerge } from '@helpers4/object';
|
|
170
|
+
|
|
171
|
+
deepMerge(target: null, sources: Record<string, unknown>[]): null
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
**Parameters:**
|
|
175
|
+
|
|
176
|
+
- `target: null` — The target object
|
|
177
|
+
- `sources: Record<string, unknown>[]` — The source objects to merge
|
|
178
|
+
|
|
179
|
+
**Returns:** `null` — The merged object
|
|
180
|
+
|
|
181
|
+
**Examples:**
|
|
182
|
+
|
|
183
|
+
*Merge two objects deeply*
|
|
184
|
+
|
|
185
|
+
Recursively merges source properties into the target object.
|
|
186
|
+
|
|
187
|
+
```typescript
|
|
188
|
+
deepMerge({ a: 1, b: { c: 2 } }, { b: { d: 3 }, e: 4 })
|
|
189
|
+
// => { a: 1, b: { c: 2, d: 3 }, e: 4 }
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
---
|
|
193
|
+
|
|
194
|
+
### `diff`
|
|
195
|
+
|
|
196
|
+
Structural object diff.
|
|
197
|
+
|
|
198
|
+
Returns `true` when both inputs are deeply equal, otherwise a
|
|
199
|
+
DiffResult describing the differences key by key.
|
|
200
|
+
|
|
201
|
+
Comparison rules:
|
|
202
|
+
- Same reference \u2192 `true`.
|
|
203
|
+
- Either side is `null`/`undefined` (and not both) \u2192 `false`.
|
|
204
|
+
- Both `Date` \u2192 epoch comparison.
|
|
205
|
+
- Both arrays \u2192 compared with `array/equalsDeep` (leaf, no diff drill-down).
|
|
206
|
+
- Special objects (Map, Set, RegExp, Promise, class instances\u2026) \u2192 reference equality.
|
|
207
|
+
- Plain objects \u2192 key-by-key, recursing up to `options.depth` levels.
|
|
208
|
+
- Mixed types (e.g. array vs object, Date vs object) \u2192 `false`.
|
|
209
|
+
|
|
210
|
+
For a boolean wrapper see equalsDeep from this category.
|
|
211
|
+
For a one-level boolean check see equalsShallow from this category.
|
|
212
|
+
|
|
213
|
+
```typescript
|
|
214
|
+
import { diff } from '@helpers4/object';
|
|
215
|
+
|
|
216
|
+
diff(objA: object | null | undefined, objB: object | null | undefined, options: DiffOptions): boolean | DiffResult
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
**Parameters:**
|
|
220
|
+
|
|
221
|
+
- `objA: object | null | undefined` — First value (object, `null`, or `undefined`).
|
|
222
|
+
- `objB: object | null | undefined` — Second value (object, `null`, or `undefined`).
|
|
223
|
+
- `options: DiffOptions` (default: `{}`) — See DiffOptions.
|
|
224
|
+
|
|
225
|
+
**Returns:** `boolean | DiffResult` — `true` when equal, otherwise a DiffResult, or `false` for incompatible types.
|
|
226
|
+
|
|
227
|
+
**Examples:**
|
|
228
|
+
|
|
229
|
+
*Compare nested objects*
|
|
230
|
+
|
|
231
|
+
Deeply compares two objects, returning true when they are structurally equal.
|
|
232
|
+
|
|
233
|
+
```typescript
|
|
234
|
+
diff({ a: { b: 1 } }, { a: { b: 1 } })
|
|
235
|
+
// => true
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
*Detect deep differences*
|
|
239
|
+
|
|
240
|
+
Returns a detailed diff object when nested values differ.
|
|
241
|
+
|
|
242
|
+
```typescript
|
|
243
|
+
diff({ a: { b: 1 } }, { a: { b: 2 } })
|
|
244
|
+
// => { a: { b: false } }
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
---
|
|
248
|
+
|
|
249
|
+
### `equalsDeep`
|
|
250
|
+
|
|
251
|
+
Recursive structural object equality.
|
|
252
|
+
|
|
253
|
+
Boolean wrapper around diff \u2014 returns `true` when the two values
|
|
254
|
+
are deeply equal according to the same rules. Use this when you only
|
|
255
|
+
need a yes/no answer; use diff when you also need to know
|
|
256
|
+
*what* differs.
|
|
257
|
+
|
|
258
|
+
For a one-level boolean check use equalsShallow.
|
|
259
|
+
|
|
260
|
+
```typescript
|
|
261
|
+
import { equalsDeep } from '@helpers4/object';
|
|
262
|
+
|
|
263
|
+
equalsDeep(objA: object | null | undefined, objB: object | null | undefined): boolean
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
**Parameters:**
|
|
267
|
+
|
|
268
|
+
- `objA: object | null | undefined` — First value (object, `null`, or `undefined`).
|
|
269
|
+
- `objB: object | null | undefined` — Second value (object, `null`, or `undefined`).
|
|
270
|
+
|
|
271
|
+
**Returns:** `boolean` — `true` if both inputs are deeply equal, `false` otherwise.
|
|
272
|
+
|
|
273
|
+
**Examples:**
|
|
274
|
+
|
|
275
|
+
*Compare nested objects*
|
|
276
|
+
|
|
277
|
+
Recursive structural equality. Returns true when the two values are deeply equal.
|
|
278
|
+
|
|
279
|
+
```typescript
|
|
280
|
+
equalsDeep({ a: { b: 1 } }, { a: { b: 1 } })
|
|
281
|
+
// => true
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
*Detect deep differences*
|
|
285
|
+
|
|
286
|
+
Returns false when nested values differ.
|
|
287
|
+
|
|
288
|
+
```typescript
|
|
289
|
+
equalsDeep({ a: { b: 1 } }, { a: { b: 2 } })
|
|
290
|
+
// => false
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
---
|
|
294
|
+
|
|
295
|
+
### `equalsShallow`
|
|
296
|
+
|
|
297
|
+
One-level (shallow) object equality.
|
|
298
|
+
|
|
299
|
+
Two objects are equal when they share the exact same set of own
|
|
300
|
+
enumerable string keys and each pair of values satisfies strict equality
|
|
301
|
+
(`===`). No recursion: nested objects/arrays are compared by reference.
|
|
302
|
+
|
|
303
|
+
Falls back to strict equality when either input is `null`, `undefined`
|
|
304
|
+
or not an object \u2014 so primitives match if and only if they are `===`.
|
|
305
|
+
Arrays are not supported; they always return `false` (unless identical
|
|
306
|
+
references). Use `array/equalsShallow` instead.
|
|
307
|
+
|
|
308
|
+
For recursive structural comparison use equalsDeep. For a diff
|
|
309
|
+
structure use diff.
|
|
310
|
+
|
|
311
|
+
```typescript
|
|
312
|
+
import { equalsShallow } from '@helpers4/object';
|
|
313
|
+
|
|
314
|
+
equalsShallow(objA: unknown, objB: unknown): boolean
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
**Parameters:**
|
|
318
|
+
|
|
319
|
+
- `objA: unknown` — First value to compare
|
|
320
|
+
- `objB: unknown` — Second value to compare
|
|
321
|
+
|
|
322
|
+
**Returns:** `boolean` — `true` if values are shallowly equal, `false` otherwise.
|
|
323
|
+
|
|
324
|
+
**Examples:**
|
|
325
|
+
|
|
326
|
+
*Compare two equal objects*
|
|
327
|
+
|
|
328
|
+
Uses JSON.stringify for a fast comparison.
|
|
329
|
+
|
|
330
|
+
```typescript
|
|
331
|
+
equalsShallow({ a: 1, b: 2 }, { a: 1, b: 2 })
|
|
332
|
+
// => true
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
---
|
|
336
|
+
|
|
337
|
+
### `get`
|
|
338
|
+
|
|
339
|
+
Gets a value from an object using a dot-notated path
|
|
340
|
+
|
|
341
|
+
```typescript
|
|
342
|
+
import { get } from '@helpers4/object';
|
|
343
|
+
|
|
344
|
+
get<T = unknown>(obj: unknown, path: string, defaultValue?: T): T | undefined
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
**Parameters:**
|
|
348
|
+
|
|
349
|
+
- `obj: unknown` — The object to get value from
|
|
350
|
+
- `path: string` — The dot-notated path (e.g., 'a.b.c')
|
|
351
|
+
- `defaultValue?: T` — Default value if path doesn't exist
|
|
352
|
+
|
|
353
|
+
**Returns:** `T | undefined` — The value at the path or default value
|
|
354
|
+
|
|
355
|
+
**Examples:**
|
|
356
|
+
|
|
357
|
+
*Access a nested property*
|
|
358
|
+
|
|
359
|
+
Uses a dot-notated path to retrieve a deeply nested value.
|
|
360
|
+
|
|
361
|
+
```typescript
|
|
362
|
+
get({ a: { b: { c: 42 } } }, 'a.b.c')
|
|
363
|
+
// => 42
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
*Return default for missing path*
|
|
367
|
+
|
|
368
|
+
Returns the default value when the path does not exist.
|
|
369
|
+
|
|
370
|
+
```typescript
|
|
371
|
+
get({ a: 1 }, 'b.c', 'default')
|
|
372
|
+
// => 'default'
|
|
373
|
+
```
|
|
374
|
+
|
|
375
|
+
---
|
|
376
|
+
|
|
377
|
+
### `groupBy`
|
|
378
|
+
|
|
379
|
+
Groups an array of items by a key derived from each item.
|
|
380
|
+
|
|
381
|
+
A thin, typed wrapper around `Object.groupBy` (ES2024) that works on
|
|
382
|
+
older targets and provides stricter return-type inference.
|
|
383
|
+
|
|
384
|
+
```typescript
|
|
385
|
+
import { groupBy } from '@helpers4/object';
|
|
386
|
+
|
|
387
|
+
groupBy<T, K extends PropertyKey>(items: readonly T[], keyFn: function): Partial<Record<K, T[]>>
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
**Parameters:**
|
|
391
|
+
|
|
392
|
+
- `items: readonly T[]` — The array to group
|
|
393
|
+
- `keyFn: function` — Function that returns the group key for each item
|
|
394
|
+
|
|
395
|
+
**Returns:** `Partial<Record<K, T[]>>` — A record mapping each key to the array of items with that key
|
|
396
|
+
|
|
397
|
+
**Examples:**
|
|
398
|
+
|
|
399
|
+
*Group numbers by parity*
|
|
400
|
+
|
|
401
|
+
Groups elements by the string key returned by the callback.
|
|
402
|
+
|
|
403
|
+
```typescript
|
|
404
|
+
groupBy([1, 2, 3, 4], n => n % 2 === 0 ? 'even' : 'odd')
|
|
405
|
+
// => { odd: [1, 3], even: [2, 4] }
|
|
406
|
+
```
|
|
407
|
+
|
|
408
|
+
*Group objects by a property*
|
|
409
|
+
|
|
410
|
+
Use a property accessor as the grouping key.
|
|
411
|
+
|
|
412
|
+
```typescript
|
|
413
|
+
const users = [
|
|
414
|
+
{ name: 'Alice', role: 'admin' },
|
|
415
|
+
{ name: 'Bob', role: 'user' },
|
|
416
|
+
{ name: 'Carol', role: 'admin' },
|
|
417
|
+
];
|
|
418
|
+
groupBy(users, u => u.role)
|
|
419
|
+
// => { admin: [{...Alice}, {...Carol}], user: [{...Bob}] }
|
|
420
|
+
```
|
|
421
|
+
|
|
422
|
+
---
|
|
423
|
+
|
|
424
|
+
### `invert`
|
|
425
|
+
|
|
426
|
+
Returns a new object with keys and values swapped.
|
|
427
|
+
If multiple keys share the same value, the last one wins.
|
|
428
|
+
|
|
429
|
+
```typescript
|
|
430
|
+
import { invert } from '@helpers4/object';
|
|
431
|
+
|
|
432
|
+
invert<K extends string, V extends PropertyKey>(obj: Record<K, V>): Record<V, K>
|
|
433
|
+
```
|
|
434
|
+
|
|
435
|
+
**Parameters:**
|
|
436
|
+
|
|
437
|
+
- `obj: Record<K, V>` — The object whose keys and values are to be swapped
|
|
438
|
+
|
|
439
|
+
**Returns:** `Record<V, K>` — A new object with values as keys and original keys as values
|
|
440
|
+
|
|
441
|
+
**Examples:**
|
|
442
|
+
|
|
443
|
+
*Swap keys and values*
|
|
444
|
+
|
|
445
|
+
Returns a new object with keys and values swapped.
|
|
446
|
+
|
|
447
|
+
```typescript
|
|
448
|
+
invert({ a: 'x', b: 'y', c: 'z' })
|
|
449
|
+
// => { x: 'a', y: 'b', z: 'c' }
|
|
450
|
+
```
|
|
451
|
+
|
|
452
|
+
*Build a reverse lookup map*
|
|
453
|
+
|
|
454
|
+
Useful when you have a code-to-label map and need label-to-code.
|
|
455
|
+
|
|
456
|
+
```typescript
|
|
457
|
+
const STATUS_LABELS = { 200: 'OK', 404: 'Not Found', 500: 'Internal Server Error' };
|
|
458
|
+
const LABEL_TO_CODE = invert(STATUS_LABELS);
|
|
459
|
+
|
|
460
|
+
LABEL_TO_CODE['OK']; // => '200'
|
|
461
|
+
```
|
|
462
|
+
|
|
463
|
+
---
|
|
464
|
+
|
|
465
|
+
### `map`
|
|
466
|
+
|
|
467
|
+
Transforms the values and/or keys of a plain object in a single pass.
|
|
468
|
+
|
|
469
|
+
Both callbacks are optional and default to identity (no transformation).
|
|
470
|
+
When `mapValue` is omitted the original values are preserved;
|
|
471
|
+
when `mapKey` is omitted the original keys are preserved.
|
|
472
|
+
|
|
473
|
+
Note: if two different keys map to the same output key the last one wins
|
|
474
|
+
(insertion order).
|
|
475
|
+
|
|
476
|
+
```typescript
|
|
477
|
+
import { map } from '@helpers4/object';
|
|
478
|
+
|
|
479
|
+
map<TObj extends Record<string, unknown>, TVal = indexedAccess, TKey extends PropertyKey = keyof TObj>(obj: TObj, mapValue?: function, mapKey?: function): Record<TKey, TVal>
|
|
480
|
+
```
|
|
481
|
+
|
|
482
|
+
**Parameters:**
|
|
483
|
+
|
|
484
|
+
- `obj: TObj` — The source object
|
|
485
|
+
- `mapValue?: function` — Callback called with `(value, key)` for each entry.
|
|
486
|
+
Defaults to identity.
|
|
487
|
+
- `mapKey?: function` — Callback called with `(key, value)` for each entry.
|
|
488
|
+
Defaults to identity.
|
|
489
|
+
|
|
490
|
+
**Returns:** `Record<TKey, TVal>` — A new object with transformed keys and/or values
|
|
491
|
+
|
|
492
|
+
**Examples:**
|
|
493
|
+
|
|
494
|
+
*Transform values*
|
|
495
|
+
|
|
496
|
+
Maps each value of an object through a transform function.
|
|
497
|
+
|
|
498
|
+
```typescript
|
|
499
|
+
map({ a: 1, b: 2 }, v => v * 10)
|
|
500
|
+
// => { a: 10, b: 20 }
|
|
501
|
+
```
|
|
502
|
+
|
|
503
|
+
*Transform keys*
|
|
504
|
+
|
|
505
|
+
Maps each key of an object through a transform function.
|
|
506
|
+
|
|
507
|
+
```typescript
|
|
508
|
+
map({ a: 1, b: 2 }, undefined, k => k.toUpperCase())
|
|
509
|
+
// => { A: 1, B: 2 }
|
|
510
|
+
```
|
|
511
|
+
|
|
512
|
+
*Transform both keys and values in a single pass*
|
|
513
|
+
|
|
514
|
+
Provide both a value mapper and a key mapper to rewrite the whole object.
|
|
515
|
+
|
|
516
|
+
```typescript
|
|
517
|
+
map(
|
|
518
|
+
{ price: 100, discount: 20 },
|
|
519
|
+
v => v / 100,
|
|
520
|
+
k => `${k}Ratio`
|
|
521
|
+
)
|
|
522
|
+
// => { priceRatio: 1, discountRatio: 0.2 }
|
|
523
|
+
```
|
|
524
|
+
|
|
525
|
+
---
|
|
526
|
+
|
|
527
|
+
### `omit`
|
|
528
|
+
|
|
529
|
+
Creates a new object without the specified keys.
|
|
530
|
+
|
|
531
|
+
```typescript
|
|
532
|
+
import { omit } from '@helpers4/object';
|
|
533
|
+
|
|
534
|
+
omit<T extends Record<string, unknown>, K extends string | number | symbol>(obj: T, keys: readonly K[]): Omit<T, K>
|
|
535
|
+
```
|
|
536
|
+
|
|
537
|
+
**Parameters:**
|
|
538
|
+
|
|
539
|
+
- `obj: T` — The source object
|
|
540
|
+
- `keys: readonly K[]` — The keys to omit
|
|
541
|
+
|
|
542
|
+
**Returns:** `Omit<T, K>` — A new object without the omitted keys
|
|
543
|
+
|
|
544
|
+
```typescript
|
|
545
|
+
import { omit } from '@helpers4/object';
|
|
546
|
+
|
|
547
|
+
omit(obj: undefined, keys: readonly string[]): undefined
|
|
548
|
+
```
|
|
549
|
+
|
|
550
|
+
**Parameters:**
|
|
551
|
+
|
|
552
|
+
- `obj: undefined` — The source object
|
|
553
|
+
- `keys: readonly string[]` — The keys to omit
|
|
554
|
+
|
|
555
|
+
**Returns:** `undefined` — A new object without the omitted keys
|
|
556
|
+
|
|
557
|
+
```typescript
|
|
558
|
+
import { omit } from '@helpers4/object';
|
|
559
|
+
|
|
560
|
+
omit(obj: null, keys: readonly string[]): null
|
|
561
|
+
```
|
|
562
|
+
|
|
563
|
+
**Parameters:**
|
|
564
|
+
|
|
565
|
+
- `obj: null` — The source object
|
|
566
|
+
- `keys: readonly string[]` — The keys to omit
|
|
567
|
+
|
|
568
|
+
**Returns:** `null` — A new object without the omitted keys
|
|
569
|
+
|
|
570
|
+
**Examples:**
|
|
571
|
+
|
|
572
|
+
*Omit specific keys*
|
|
573
|
+
|
|
574
|
+
Creates a new object without the specified keys.
|
|
575
|
+
|
|
576
|
+
```typescript
|
|
577
|
+
omit({ a: 1, b: 2, c: 3 }, ['b'])
|
|
578
|
+
// => { a: 1, c: 3 }
|
|
579
|
+
```
|
|
580
|
+
|
|
581
|
+
*Remove sensitive fields*
|
|
582
|
+
|
|
583
|
+
Useful to strip sensitive data before sending to client.
|
|
584
|
+
|
|
585
|
+
```typescript
|
|
586
|
+
const user = { id: 1, name: 'Alice', password: 'secret', token: 'abc123' };
|
|
587
|
+
omit(user, ['password', 'token'])
|
|
588
|
+
// => { id: 1, name: 'Alice' }
|
|
589
|
+
```
|
|
590
|
+
|
|
591
|
+
---
|
|
592
|
+
|
|
593
|
+
### `pick`
|
|
594
|
+
|
|
595
|
+
Creates a new object with only the specified keys.
|
|
596
|
+
|
|
597
|
+
```typescript
|
|
598
|
+
import { pick } from '@helpers4/object';
|
|
599
|
+
|
|
600
|
+
pick<T extends Record<string, unknown>, K extends string | number | symbol>(obj: T, keys: readonly K[]): Pick<T, K>
|
|
601
|
+
```
|
|
602
|
+
|
|
603
|
+
**Parameters:**
|
|
604
|
+
|
|
605
|
+
- `obj: T` — The source object
|
|
606
|
+
- `keys: readonly K[]` — The keys to pick
|
|
607
|
+
|
|
608
|
+
**Returns:** `Pick<T, K>` — A new object with only the picked keys
|
|
609
|
+
|
|
610
|
+
```typescript
|
|
611
|
+
import { pick } from '@helpers4/object';
|
|
612
|
+
|
|
613
|
+
pick(obj: undefined, keys: readonly string[]): undefined
|
|
614
|
+
```
|
|
615
|
+
|
|
616
|
+
**Parameters:**
|
|
617
|
+
|
|
618
|
+
- `obj: undefined` — The source object
|
|
619
|
+
- `keys: readonly string[]` — The keys to pick
|
|
620
|
+
|
|
621
|
+
**Returns:** `undefined` — A new object with only the picked keys
|
|
622
|
+
|
|
623
|
+
```typescript
|
|
624
|
+
import { pick } from '@helpers4/object';
|
|
625
|
+
|
|
626
|
+
pick(obj: null, keys: readonly string[]): null
|
|
627
|
+
```
|
|
628
|
+
|
|
629
|
+
**Parameters:**
|
|
630
|
+
|
|
631
|
+
- `obj: null` — The source object
|
|
632
|
+
- `keys: readonly string[]` — The keys to pick
|
|
633
|
+
|
|
634
|
+
**Returns:** `null` — A new object with only the picked keys
|
|
635
|
+
|
|
636
|
+
**Examples:**
|
|
637
|
+
|
|
638
|
+
*Pick specific keys*
|
|
639
|
+
|
|
640
|
+
Creates a new object with only the specified keys.
|
|
641
|
+
|
|
642
|
+
```typescript
|
|
643
|
+
pick({ a: 1, b: 2, c: 3 }, ['a', 'c'])
|
|
644
|
+
// => { a: 1, c: 3 }
|
|
645
|
+
```
|
|
646
|
+
|
|
647
|
+
*Extract user fields*
|
|
648
|
+
|
|
649
|
+
Useful to select only the fields you need from an object.
|
|
650
|
+
|
|
651
|
+
```typescript
|
|
652
|
+
const user = { id: 1, name: 'Alice', email: 'alice@example.com', password: 'secret' };
|
|
653
|
+
pick(user, ['id', 'name', 'email'])
|
|
654
|
+
// => { id: 1, name: 'Alice', email: 'alice@example.com' }
|
|
655
|
+
```
|
|
656
|
+
|
|
657
|
+
---
|
|
658
|
+
|
|
659
|
+
### `removeUndefinedNull`
|
|
660
|
+
|
|
661
|
+
Remove null and undefined values from an object.
|
|
662
|
+
|
|
663
|
+
```typescript
|
|
664
|
+
import { removeUndefinedNull } from '@helpers4/object';
|
|
665
|
+
|
|
666
|
+
removeUndefinedNull<T extends Record<string, string | number | boolean | null | undefined>>(obj: T): Partial<T>
|
|
667
|
+
```
|
|
668
|
+
|
|
669
|
+
**Parameters:**
|
|
670
|
+
|
|
671
|
+
- `obj: T` — an object
|
|
672
|
+
|
|
673
|
+
**Returns:** `Partial<T>` — A shallow copy of the object without null or undefined values
|
|
674
|
+
|
|
675
|
+
```typescript
|
|
676
|
+
import { removeUndefinedNull } from '@helpers4/object';
|
|
677
|
+
|
|
678
|
+
removeUndefinedNull(obj: null): null
|
|
679
|
+
```
|
|
680
|
+
|
|
681
|
+
**Parameters:**
|
|
682
|
+
|
|
683
|
+
- `obj: null` — a null object
|
|
684
|
+
|
|
685
|
+
**Returns:** `null` — null
|
|
686
|
+
|
|
687
|
+
```typescript
|
|
688
|
+
import { removeUndefinedNull } from '@helpers4/object';
|
|
689
|
+
|
|
690
|
+
removeUndefinedNull(obj: undefined): undefined
|
|
691
|
+
```
|
|
692
|
+
|
|
693
|
+
**Parameters:**
|
|
694
|
+
|
|
695
|
+
- `obj: undefined` — an undefined object
|
|
696
|
+
|
|
697
|
+
**Returns:** `undefined` — undefined
|
|
698
|
+
|
|
699
|
+
**Examples:**
|
|
700
|
+
|
|
701
|
+
*Strip null and undefined values*
|
|
702
|
+
|
|
703
|
+
Returns a shallow copy of the object without null or undefined properties.
|
|
704
|
+
|
|
705
|
+
```typescript
|
|
706
|
+
removeUndefinedNull({ a: 1, b: null, c: undefined, d: 'ok' })
|
|
707
|
+
// => { a: 1, d: 'ok' }
|
|
708
|
+
```
|
|
709
|
+
|
|
710
|
+
---
|
|
711
|
+
|
|
712
|
+
### `safeJsonParse`
|
|
713
|
+
|
|
714
|
+
Parses a JSON string, returning `null` (or a fallback) on any parse failure.
|
|
715
|
+
|
|
716
|
+
Unlike `JSON.parse`, this never throws. Invalid JSON strings and other
|
|
717
|
+
parsing edge-cases resolve to `null` or the provided `fallback`.
|
|
718
|
+
|
|
719
|
+
```typescript
|
|
720
|
+
import { safeJsonParse } from '@helpers4/object';
|
|
721
|
+
|
|
722
|
+
safeJsonParse<T>(input: string): T | null
|
|
723
|
+
```
|
|
724
|
+
|
|
725
|
+
**Parameters:**
|
|
726
|
+
|
|
727
|
+
- `input: string` — The JSON string to parse.
|
|
728
|
+
|
|
729
|
+
**Returns:** `T | null` — The parsed value typed as `T`, or `fallback` on failure.
|
|
730
|
+
|
|
731
|
+
```typescript
|
|
732
|
+
import { safeJsonParse } from '@helpers4/object';
|
|
733
|
+
|
|
734
|
+
safeJsonParse<T>(input: string, fallback: T): T
|
|
735
|
+
```
|
|
736
|
+
|
|
737
|
+
**Parameters:**
|
|
738
|
+
|
|
739
|
+
- `input: string` — The JSON string to parse.
|
|
740
|
+
- `fallback: T` — Value returned on failure. Defaults to `null` when omitted.
|
|
741
|
+
|
|
742
|
+
**Returns:** `T` — The parsed value typed as `T`, or `fallback` on failure.
|
|
743
|
+
|
|
744
|
+
**Examples:**
|
|
745
|
+
|
|
746
|
+
*Parse valid JSON*
|
|
747
|
+
|
|
748
|
+
Returns the parsed value when the input is valid JSON.
|
|
749
|
+
|
|
750
|
+
```typescript
|
|
751
|
+
safeJsonParse<{ a: number }>('{"a":1}')
|
|
752
|
+
// => { a: 1 }
|
|
753
|
+
```
|
|
754
|
+
|
|
755
|
+
*Return null on invalid input*
|
|
756
|
+
|
|
757
|
+
Returns null instead of throwing when JSON is malformed.
|
|
758
|
+
|
|
759
|
+
```typescript
|
|
760
|
+
safeJsonParse('invalid')
|
|
761
|
+
// => null
|
|
762
|
+
```
|
|
763
|
+
|
|
764
|
+
*Use a fallback value*
|
|
765
|
+
|
|
766
|
+
Returns the provided fallback when parsing fails.
|
|
767
|
+
|
|
768
|
+
```typescript
|
|
769
|
+
safeJsonParse('invalid', [])
|
|
770
|
+
// => []
|
|
771
|
+
```
|
|
772
|
+
|
|
773
|
+
---
|
|
774
|
+
|
|
775
|
+
### `set`
|
|
776
|
+
|
|
777
|
+
Sets a value in an object using a dot-notated path
|
|
778
|
+
|
|
779
|
+
```typescript
|
|
780
|
+
import { set } from '@helpers4/object';
|
|
781
|
+
|
|
782
|
+
set(obj: Record<string, unknown>, path: string, value: unknown): Record<string, unknown>
|
|
783
|
+
```
|
|
784
|
+
|
|
785
|
+
**Parameters:**
|
|
786
|
+
|
|
787
|
+
- `obj: Record<string, unknown>` — The object to set value in
|
|
788
|
+
- `path: string` — The dot-notated path (e.g., 'a.b.c')
|
|
789
|
+
- `value: unknown` — The value to set
|
|
790
|
+
|
|
791
|
+
**Returns:** `Record<string, unknown>` — The modified object
|
|
792
|
+
|
|
793
|
+
**Examples:**
|
|
794
|
+
|
|
795
|
+
*Set a nested property*
|
|
796
|
+
|
|
797
|
+
Creates intermediate objects as needed along the dot-notated path.
|
|
798
|
+
|
|
799
|
+
```typescript
|
|
800
|
+
set({}, 'a.b.c', 42)
|
|
801
|
+
// => { a: { b: { c: 42 } } }
|
|
802
|
+
```
|
|
803
|
+
|
|
804
|
+
---
|