@helpers4/object 3.0.0-alpha.2 → 3.0.1
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 +8 -0
- package/lib/index.d.ts +314 -58
- package/lib/index.js +252 -23
- package/lib/index.js.map +1 -1
- package/llms.txt +381 -2
- package/meta/api.json +351 -1
- package/meta/examples.json +120 -0
- package/package.json +10 -2
package/README.md
CHANGED
|
@@ -12,11 +12,13 @@ A set of helpers for working with URLs.
|
|
|
12
12
|
[https://helpers4.dev/typescript/categories/object/](https://helpers4.dev/typescript/categories/object/)
|
|
13
13
|
|
|
14
14
|
<!-- AUTOMATIC-METHODS -->
|
|
15
|
+
- clone
|
|
15
16
|
- cloneDeep
|
|
16
17
|
- compact
|
|
17
18
|
- diff
|
|
18
19
|
- equalsDeep
|
|
19
20
|
- equalsShallow
|
|
21
|
+
- flatten
|
|
20
22
|
- get
|
|
21
23
|
- groupBy
|
|
22
24
|
- invert
|
|
@@ -25,10 +27,16 @@ A set of helpers for working with URLs.
|
|
|
25
27
|
- map
|
|
26
28
|
- mergeDeep
|
|
27
29
|
- omit
|
|
30
|
+
- omitBy
|
|
31
|
+
- parsePropertyPath
|
|
28
32
|
- pick
|
|
33
|
+
- pickBy
|
|
29
34
|
- removeUndefinedNull
|
|
30
35
|
- safeJsonParse
|
|
31
36
|
- set
|
|
37
|
+
- unflatten
|
|
38
|
+
- unset
|
|
39
|
+
- update
|
|
32
40
|
<!-- /AUTOMATIC-METHODS -->
|
|
33
41
|
|
|
34
42
|
## See
|
package/lib/index.d.ts
CHANGED
|
@@ -1,3 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of helpers4.
|
|
3
|
+
* Copyright (C) 2025 baxyz
|
|
4
|
+
* SPDX-License-Identifier: LGPL-3.0-or-later
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Creates a shallow copy of a value — one level deep, unlike {@link cloneDeep}.
|
|
8
|
+
*
|
|
9
|
+
* Unlike a plain `{ ...value }` spread, this correctly reconstructs `Date`,
|
|
10
|
+
* `Map`, `Set`, and arrays instead of producing an empty (or wrong-shaped)
|
|
11
|
+
* plain object for them. Primitives are returned as-is. Any other object
|
|
12
|
+
* (including class instances not listed above) has its own enumerable string
|
|
13
|
+
* keys shallow-copied into a plain object — the same fallback `cloneDeep`
|
|
14
|
+
* uses, so the two stay consistent for types neither one special-cases.
|
|
15
|
+
*
|
|
16
|
+
* @param value - The value to shallow-clone
|
|
17
|
+
* @returns A shallow copy of `value`
|
|
18
|
+
* @example
|
|
19
|
+
* clone({ a: { b: 1 } })
|
|
20
|
+
* // => { a: { b: 1 } } — new object, but `a` is the *same* nested reference
|
|
21
|
+
* @example
|
|
22
|
+
* clone(new Date('2024-01-01')) // => new Date with the same timestamp
|
|
23
|
+
* clone(new Map([['a', 1]])) // => new Map with the same entries
|
|
24
|
+
* clone([1, 2, 3]) // => new array, same elements
|
|
25
|
+
* @since 3.0.0
|
|
26
|
+
*/
|
|
27
|
+
declare function clone<T>(value: T): T;
|
|
28
|
+
|
|
1
29
|
/**
|
|
2
30
|
* This file is part of helpers4.
|
|
3
31
|
* Copyright (C) 2025 baxyz
|
|
@@ -162,6 +190,37 @@ declare function equalsDeep(objA: object | undefined | null, objB: object | unde
|
|
|
162
190
|
*/
|
|
163
191
|
declare function equalsShallow(objA: unknown, objB: unknown): boolean;
|
|
164
192
|
|
|
193
|
+
/**
|
|
194
|
+
* This file is part of helpers4.
|
|
195
|
+
* Copyright (C) 2025 baxyz
|
|
196
|
+
* SPDX-License-Identifier: LGPL-3.0-or-later
|
|
197
|
+
*/
|
|
198
|
+
/**
|
|
199
|
+
* Flattens a nested object into a single-level object whose keys are the
|
|
200
|
+
* dot-notation path to each leaf value. The inverse of {@link unflatten}.
|
|
201
|
+
*
|
|
202
|
+
* Only **plain objects** are recursed into — arrays, `Date`, `Map`, `RegExp`,
|
|
203
|
+
* class instances, and empty plain objects `{}` are kept as opaque leaf
|
|
204
|
+
* values. This keeps `flatten`/`unflatten` a clean, invertible pair: arrays
|
|
205
|
+
* can't be losslessly told apart from plain objects once reduced to dotted
|
|
206
|
+
* keys, so this implementation doesn't attempt it.
|
|
207
|
+
*
|
|
208
|
+
* Caveat shared by every dotted-path flattening scheme: a key that itself
|
|
209
|
+
* contains a literal `.` is indistinguishable from real nesting once
|
|
210
|
+
* flattened (`{ 'a.b': 1 }` and `{ a: { b: 1 } }` both produce `{ 'a.b': 1 }`).
|
|
211
|
+
*
|
|
212
|
+
* @param obj - The object to flatten
|
|
213
|
+
* @returns A single-level object with dot-notation keys
|
|
214
|
+
* @example
|
|
215
|
+
* flatten({ a: { b: { c: 1 }, d: 2 } })
|
|
216
|
+
* // => { 'a.b.c': 1, 'a.d': 2 }
|
|
217
|
+
* @example
|
|
218
|
+
* flatten({ a: [1, 2], b: new Date(0) })
|
|
219
|
+
* // => { a: [1, 2], b: Date } (arrays and special objects stay as leaves)
|
|
220
|
+
* @since 3.0.0
|
|
221
|
+
*/
|
|
222
|
+
declare function flatten(obj: Record<string, unknown>): Record<string, unknown>;
|
|
223
|
+
|
|
165
224
|
/**
|
|
166
225
|
* This file is part of helpers4.
|
|
167
226
|
* Copyright (C) 2025 baxyz
|
|
@@ -175,6 +234,101 @@ declare const UNSAFE_KEY_LIST: readonly ["__proto__", "constructor", "prototype"
|
|
|
175
234
|
/** @ignore */
|
|
176
235
|
type UnsafeKey = (typeof UNSAFE_KEY_LIST)[number];
|
|
177
236
|
|
|
237
|
+
/**
|
|
238
|
+
* This file is part of helpers4.
|
|
239
|
+
* Copyright (C) 2025 baxyz
|
|
240
|
+
* SPDX-License-Identifier: LGPL-3.0-or-later
|
|
241
|
+
*/
|
|
242
|
+
/**
|
|
243
|
+
* Converts a union type to an intersection type: `A | B | C` → `A & B & C`.
|
|
244
|
+
*
|
|
245
|
+
* Uses conditional-type distribution and the contravariant position of a
|
|
246
|
+
* function parameter to collapse the union into an intersection.
|
|
247
|
+
*
|
|
248
|
+
* @example
|
|
249
|
+
* type Union = { a: number } | { b: string } | { c: boolean };
|
|
250
|
+
* type Intersection = UnionToIntersection<Union>;
|
|
251
|
+
* // { a: number } & { b: string } & { c: boolean }
|
|
252
|
+
*
|
|
253
|
+
* type Keys = UnionToIntersection<'a' | 'b'>;
|
|
254
|
+
* // 'a' & 'b' (resolves to never for disjoint literals)
|
|
255
|
+
* @since 3.0.0
|
|
256
|
+
*/
|
|
257
|
+
type UnionToIntersection<U> = (U extends unknown ? (x: U) => void : never) extends (x: infer I) => void ? I : never;
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* This file is part of helpers4.
|
|
261
|
+
* Copyright (C) 2025 baxyz
|
|
262
|
+
* SPDX-License-Identifier: LGPL-3.0-or-later
|
|
263
|
+
*/
|
|
264
|
+
/**
|
|
265
|
+
* Returns `never` for `null`/`undefined`, otherwise `keyof T`.
|
|
266
|
+
*
|
|
267
|
+
* Used instead of inlining `keyof NonNullable<T>` at each `DeepGet` recursion
|
|
268
|
+
* step — TypeScript doesn't evaluate that expression eagerly inside a
|
|
269
|
+
* recursive generic, so `keyof` ends up applied to an unresolved conditional
|
|
270
|
+
* type instead of a concrete one. That collapses the whole recursive chain to
|
|
271
|
+
* `never` (rather than `unknown`) the moment a path travels through a
|
|
272
|
+
* property whose value is `null`, even though `null` itself is never in
|
|
273
|
+
* `Path`. Checking the null-ness first, in its own conditional, forces eager
|
|
274
|
+
* resolution and keeps that case at `unknown` as intended.
|
|
275
|
+
* @ignore
|
|
276
|
+
*/
|
|
277
|
+
type KeysOf<T> = T extends null | undefined ? never : keyof T;
|
|
278
|
+
/**
|
|
279
|
+
* Resolves the value type at a given `Path` within `T`.
|
|
280
|
+
*
|
|
281
|
+
* Returns `unknown` when any key in `Path` is not present in the corresponding
|
|
282
|
+
* level of `T`. An empty path resolves to `T` itself. A path segment that goes
|
|
283
|
+
* through an optional property keeps the result nullable (`V | undefined`)
|
|
284
|
+
* instead of degrading to `unknown`.
|
|
285
|
+
*
|
|
286
|
+
* @example
|
|
287
|
+
* type Obj = { a: { b: { c: number } } };
|
|
288
|
+
*
|
|
289
|
+
* DeepGet<Obj, ['a', 'b', 'c']> // => number
|
|
290
|
+
* DeepGet<Obj, ['a', 'b']> // => { c: number }
|
|
291
|
+
* DeepGet<Obj, ['a', 'x']> // => unknown
|
|
292
|
+
* DeepGet<Obj, []> // => Obj
|
|
293
|
+
*
|
|
294
|
+
* type WithOptional = { a?: { b: number } };
|
|
295
|
+
* DeepGet<WithOptional, ['a', 'b']> // => number | undefined
|
|
296
|
+
* @since 3.0.0
|
|
297
|
+
*/
|
|
298
|
+
type DeepGet<T, Path extends readonly PropertyKey[]> = Path extends readonly [] ? T : Path extends readonly [infer K, ...infer Rest extends readonly PropertyKey[]] ? K extends KeysOf<T> ? DeepGet<NonNullable<T>[K & keyof NonNullable<T>], Rest> | (undefined extends T ? undefined : never) : unknown : unknown;
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* This file is part of helpers4.
|
|
302
|
+
* Copyright (C) 2025 baxyz
|
|
303
|
+
* SPDX-License-Identifier: LGPL-3.0-or-later
|
|
304
|
+
*/
|
|
305
|
+
/**
|
|
306
|
+
* Builds a brand-new nested object type from the remaining path segments and a leaf value type.
|
|
307
|
+
* Used by `DeepSet` once a path segment no longer matches an existing key on T.
|
|
308
|
+
* @ignore
|
|
309
|
+
*/
|
|
310
|
+
type BuildPath<Path extends readonly PropertyKey[], V> = Path extends readonly [infer K extends PropertyKey, ...infer Rest extends readonly PropertyKey[]] ? Record<K, BuildPath<Rest, V>> : V;
|
|
311
|
+
/**
|
|
312
|
+
* Produces the type of `T` after replacing the value at `Path` with `V`.
|
|
313
|
+
*
|
|
314
|
+
* When a key in `Path` is absent from the corresponding level of `T`, that level
|
|
315
|
+
* (and everything below it) is added as a new field instead of resolving to
|
|
316
|
+
* `never` — mirroring how `set()` creates intermediate objects at runtime.
|
|
317
|
+
*
|
|
318
|
+
* @example
|
|
319
|
+
* type Obj = { a: { b: number; c: string } };
|
|
320
|
+
*
|
|
321
|
+
* DeepSet<Obj, ['a', 'b'], string>
|
|
322
|
+
* // => { a: { b: string; c: string } }
|
|
323
|
+
*
|
|
324
|
+
* DeepSet<Obj, ['a', 'x'], boolean>
|
|
325
|
+
* // => { a: { b: number; c: string } & { x: boolean } }
|
|
326
|
+
* @since 3.0.0
|
|
327
|
+
*/
|
|
328
|
+
type DeepSet<T, Path extends readonly PropertyKey[], V> = Path extends readonly [] ? V : Path extends readonly [infer K extends PropertyKey, ...infer Rest extends readonly PropertyKey[]] ? T extends object ? K extends keyof T ? {
|
|
329
|
+
[P in keyof T]: P extends K ? DeepSet<T[K], Rest, V> : T[P];
|
|
330
|
+
} : T & Record<K, BuildPath<Rest, V>> : BuildPath<Path, V> : never;
|
|
331
|
+
|
|
178
332
|
/**
|
|
179
333
|
* This file is part of helpers4.
|
|
180
334
|
* Copyright (C) 2025 baxyz
|
|
@@ -222,12 +376,6 @@ type ParsePath<P extends string | readonly PropertyKey[]> = P extends string ? P
|
|
|
222
376
|
* @ignore
|
|
223
377
|
*/
|
|
224
378
|
type ContainsUnsafeStringKey<Keys extends readonly PropertyKey[]> = Keys extends readonly [infer K, ...infer Rest extends readonly PropertyKey[]] ? K extends UnsafeKey ? true : ContainsUnsafeStringKey<Rest> : false;
|
|
225
|
-
/**
|
|
226
|
-
* Converts a union to an intersection: `A | B | C` → `A & B & C`.
|
|
227
|
-
* Used to derive the return type of `mergeDeep` from a tuple of source types.
|
|
228
|
-
* @ignore
|
|
229
|
-
*/
|
|
230
|
-
type UnionToIntersection<U> = (U extends unknown ? (x: U) => void : never) extends (x: infer I) => void ? I : never;
|
|
231
379
|
/**
|
|
232
380
|
* Return type of `mergeDeep`: intersection of all source types.
|
|
233
381
|
*
|
|
@@ -237,57 +385,6 @@ type UnionToIntersection<U> = (U extends unknown ? (x: U) => void : never) exten
|
|
|
237
385
|
* MergeResult<[{ a: { b: number } }, { a: { c: string } }]> // { a: { b: number } & { c: string } }
|
|
238
386
|
*/
|
|
239
387
|
type MergeResult<T extends object[]> = UnionToIntersection<T[number]>;
|
|
240
|
-
/**
|
|
241
|
-
* Returns `never` for `null`/`undefined`, otherwise `keyof T`.
|
|
242
|
-
*
|
|
243
|
-
* Used instead of inlining `keyof NonNullable<T>` at each `DeepGet` recursion
|
|
244
|
-
* step — TypeScript doesn't evaluate that expression eagerly inside a
|
|
245
|
-
* recursive generic, so `keyof` ends up applied to an unresolved conditional
|
|
246
|
-
* type instead of a concrete one. That collapses the whole recursive chain to
|
|
247
|
-
* `never` (rather than `unknown`) the moment a path travels through a
|
|
248
|
-
* property whose value is `null`, even though `null` itself is never in
|
|
249
|
-
* `Path`. Checking the null-ness first, in its own conditional, forces eager
|
|
250
|
-
* resolution and keeps that case at `unknown` as intended.
|
|
251
|
-
* @ignore
|
|
252
|
-
*/
|
|
253
|
-
type KeysOf<T> = T extends null | undefined ? never : keyof T;
|
|
254
|
-
/**
|
|
255
|
-
* Resolves the value type at a given path within T.
|
|
256
|
-
* Returns `unknown` when the path doesn't match the shape of T. A path segment
|
|
257
|
-
* that goes through an optional property keeps the result nullable
|
|
258
|
-
* (`V | undefined`) instead of degrading to `unknown`.
|
|
259
|
-
*
|
|
260
|
-
* @ignore
|
|
261
|
-
* @example
|
|
262
|
-
* DeepGet<{ a: { b: number } }, ['a', 'b']> // => number
|
|
263
|
-
* DeepGet<{ a: { b: number } }, ['a', 'x']> // => unknown
|
|
264
|
-
* DeepGet<{ a: number }, []> // => { a: number }
|
|
265
|
-
* DeepGet<{ a?: { b: number } }, ['a', 'b']> // => number | undefined
|
|
266
|
-
* DeepGet<{ a: { b: null } }, ['a', 'b', 'c']> // => unknown (not never)
|
|
267
|
-
*/
|
|
268
|
-
type DeepGet<T, Path extends readonly PropertyKey[]> = Path extends readonly [] ? T : Path extends readonly [infer K, ...infer Rest extends readonly PropertyKey[]] ? K extends KeysOf<T> ? DeepGet<NonNullable<T>[K & keyof NonNullable<T>], Rest> | (undefined extends T ? undefined : never) : unknown : unknown;
|
|
269
|
-
/**
|
|
270
|
-
* Builds a brand-new nested object type from the remaining path segments and a leaf value type.
|
|
271
|
-
* Used by `DeepSet` once a path segment no longer matches an existing key on T.
|
|
272
|
-
* @ignore
|
|
273
|
-
*/
|
|
274
|
-
type BuildPath<Path extends readonly PropertyKey[], V> = Path extends readonly [infer K extends PropertyKey, ...infer Rest extends readonly PropertyKey[]] ? Record<K, BuildPath<Rest, V>> : V;
|
|
275
|
-
/**
|
|
276
|
-
* Produces the type of T after setting the value at Path to V.
|
|
277
|
-
* When a key in Path is not present at the corresponding level of T, that level (and
|
|
278
|
-
* everything below it) is added as a new field instead of resolving to `never` — matching
|
|
279
|
-
* the runtime behavior of `set`, which creates intermediate objects as needed.
|
|
280
|
-
*
|
|
281
|
-
* @ignore
|
|
282
|
-
* @example
|
|
283
|
-
* DeepSet<{ a: { b: number } }, ['a', 'b'], string>
|
|
284
|
-
* // => { a: { b: string } }
|
|
285
|
-
* DeepSet<{ a: { b: number } }, ['a', 'c'], string>
|
|
286
|
-
* // => { a: { b: number } & { c: string } }
|
|
287
|
-
*/
|
|
288
|
-
type DeepSet<T, Path extends readonly PropertyKey[], V> = Path extends readonly [] ? V : Path extends readonly [infer K extends PropertyKey, ...infer Rest extends readonly PropertyKey[]] ? K extends keyof T ? {
|
|
289
|
-
[P in keyof T]: P extends K ? DeepSet<T[K], Rest, V> : T[P];
|
|
290
|
-
} : T & Record<K, BuildPath<Rest, V>> : never;
|
|
291
388
|
|
|
292
389
|
/**
|
|
293
390
|
* This file is part of helpers4.
|
|
@@ -549,6 +646,60 @@ declare function omit<T extends Record<string, unknown>, K extends keyof T>(obj:
|
|
|
549
646
|
declare function omit(obj: undefined, keys: readonly string[]): undefined;
|
|
550
647
|
declare function omit(obj: null, keys: readonly string[]): null;
|
|
551
648
|
|
|
649
|
+
/**
|
|
650
|
+
* This file is part of helpers4.
|
|
651
|
+
* Copyright (C) 2025 baxyz
|
|
652
|
+
* SPDX-License-Identifier: LGPL-3.0-or-later
|
|
653
|
+
*/
|
|
654
|
+
/**
|
|
655
|
+
* Creates a new object without the own enumerable entries for which
|
|
656
|
+
* `predicate` returns `true`.
|
|
657
|
+
*
|
|
658
|
+
* Complements {@link omit} for when the keys to remove aren't known ahead of
|
|
659
|
+
* time — `omit` takes an explicit key list, `omitBy` takes a predicate.
|
|
660
|
+
*
|
|
661
|
+
* @param obj - The source object. `null`/`undefined` pass through unchanged.
|
|
662
|
+
* @param predicate - Called with `(value, key)` for each own enumerable entry
|
|
663
|
+
* @returns A new object without the matching entries
|
|
664
|
+
* @example
|
|
665
|
+
* omitBy({ a: 1, b: undefined, c: 2 }, (value) => value === undefined)
|
|
666
|
+
* // => { a: 1, c: 2 }
|
|
667
|
+
* @since 3.0.0
|
|
668
|
+
*/
|
|
669
|
+
declare function omitBy<T extends Record<string, unknown>>(obj: T | undefined | null, predicate: (value: T[keyof T], key: keyof T) => boolean): Partial<T> | undefined | null;
|
|
670
|
+
|
|
671
|
+
/**
|
|
672
|
+
* This file is part of helpers4.
|
|
673
|
+
* Copyright (C) 2025 baxyz
|
|
674
|
+
* SPDX-License-Identifier: LGPL-3.0-or-later
|
|
675
|
+
*/
|
|
676
|
+
/**
|
|
677
|
+
* Parses a dot/bracket-notation property path into an array of string/number
|
|
678
|
+
* key segments — the same notation accepted by {@link get} and {@link set}.
|
|
679
|
+
*
|
|
680
|
+
* - Dot separators (`.`) split segments; each segment becomes a string key.
|
|
681
|
+
* - Bracket indices (`[n]`) become number keys.
|
|
682
|
+
* - A leading `.` is treated as "current level" and stripped before parsing,
|
|
683
|
+
* so `.[0]` ≡ `[0]` and `.a.b` ≡ `a.b`.
|
|
684
|
+
* - Empty string (or a bare `.`) returns `['']` (addresses the `''` key on the root object).
|
|
685
|
+
* - Consecutive dots (`a..b`) produce an empty-string segment: `['a', '', 'b']`.
|
|
686
|
+
*
|
|
687
|
+
* Results are cached (up to 500 distinct path strings, oldest evicted first)
|
|
688
|
+
* since real-world callers tend to reuse a small, fixed set of literal paths.
|
|
689
|
+
*
|
|
690
|
+
* @param path - The dot/bracket-notation path string to parse
|
|
691
|
+
* @returns The parsed key segments
|
|
692
|
+
* @throws {RangeError} When non-bracket text trails the last `]` within a
|
|
693
|
+
* dot-segment (e.g. `'a[0]b'` is ambiguous — use `'a[0].b'` instead)
|
|
694
|
+
* @example
|
|
695
|
+
* parsePropertyPath('a.b.c') // => ['a', 'b', 'c']
|
|
696
|
+
* parsePropertyPath('layers[1].x') // => ['layers', 1, 'x']
|
|
697
|
+
* parsePropertyPath('.[0]') // => [0] (leading dot stripped)
|
|
698
|
+
* parsePropertyPath('a..b') // => ['a', '', 'b'] (empty segment preserved)
|
|
699
|
+
* @since 3.0.0
|
|
700
|
+
*/
|
|
701
|
+
declare function parsePropertyPath(path: string): readonly (string | number)[];
|
|
702
|
+
|
|
552
703
|
/**
|
|
553
704
|
* This file is part of helpers4.
|
|
554
705
|
* Copyright (C) 2025 baxyz
|
|
@@ -570,6 +721,28 @@ declare function pick<T extends Record<string, unknown>, K extends keyof T>(obj:
|
|
|
570
721
|
declare function pick(obj: undefined, keys: readonly string[]): undefined;
|
|
571
722
|
declare function pick(obj: null, keys: readonly string[]): null;
|
|
572
723
|
|
|
724
|
+
/**
|
|
725
|
+
* This file is part of helpers4.
|
|
726
|
+
* Copyright (C) 2025 baxyz
|
|
727
|
+
* SPDX-License-Identifier: LGPL-3.0-or-later
|
|
728
|
+
*/
|
|
729
|
+
/**
|
|
730
|
+
* Creates a new object with only the own enumerable entries for which
|
|
731
|
+
* `predicate` returns `true`.
|
|
732
|
+
*
|
|
733
|
+
* Complements {@link pick} for when the keys to keep aren't known ahead of
|
|
734
|
+
* time — `pick` takes an explicit key list, `pickBy` takes a predicate.
|
|
735
|
+
*
|
|
736
|
+
* @param obj - The source object. `null`/`undefined` pass through unchanged.
|
|
737
|
+
* @param predicate - Called with `(value, key)` for each own enumerable entry
|
|
738
|
+
* @returns A new object with only the matching entries
|
|
739
|
+
* @example
|
|
740
|
+
* pickBy({ a: 1, b: 0, c: 2 }, (value) => value > 0)
|
|
741
|
+
* // => { a: 1, c: 2 }
|
|
742
|
+
* @since 3.0.0
|
|
743
|
+
*/
|
|
744
|
+
declare function pickBy<T extends Record<string, unknown>>(obj: T | undefined | null, predicate: (value: T[keyof T], key: keyof T) => boolean): Partial<T> | undefined | null;
|
|
745
|
+
|
|
573
746
|
/**
|
|
574
747
|
* This file is part of helpers4.
|
|
575
748
|
* Copyright (C) 2025 baxyz
|
|
@@ -671,5 +844,88 @@ declare function safeJsonParse<T>(input: string, fallback: T): T;
|
|
|
671
844
|
*/
|
|
672
845
|
declare function set<T extends object, const P extends string | readonly PropertyKey[], V extends DeepGet<T, ParsePath<P>>>(obj: T, path: P, value: V): string extends P ? T : readonly PropertyKey[] extends P ? T : ContainsUnsafeStringKey<ParsePath<P>> extends true ? T : DeepSet<T, ParsePath<P>, V>;
|
|
673
846
|
|
|
674
|
-
|
|
847
|
+
/**
|
|
848
|
+
* This file is part of helpers4.
|
|
849
|
+
* Copyright (C) 2025 baxyz
|
|
850
|
+
* SPDX-License-Identifier: LGPL-3.0-or-later
|
|
851
|
+
*/
|
|
852
|
+
/**
|
|
853
|
+
* Rebuilds a nested object from a single-level object whose keys are
|
|
854
|
+
* dot-notation paths. The inverse of {@link flatten}.
|
|
855
|
+
*
|
|
856
|
+
* Uses {@link set} internally, so intermediate nodes are always created as
|
|
857
|
+
* plain objects (never arrays — see {@link flatten}'s doc for why), and any
|
|
858
|
+
* key segment equal to `__proto__`, `constructor`, or `prototype` is silently
|
|
859
|
+
* rejected (same prototype-pollution guard as `set`).
|
|
860
|
+
*
|
|
861
|
+
* @param obj - A single-level object with dot-notation keys
|
|
862
|
+
* @returns The rebuilt nested object
|
|
863
|
+
* @example
|
|
864
|
+
* unflatten({ 'a.b.c': 1, 'a.d': 2 })
|
|
865
|
+
* // => { a: { b: { c: 1 }, d: 2 } }
|
|
866
|
+
* @since 3.0.0
|
|
867
|
+
*/
|
|
868
|
+
declare function unflatten(obj: Record<string, unknown>): Record<string, unknown>;
|
|
869
|
+
|
|
870
|
+
/**
|
|
871
|
+
* This file is part of helpers4.
|
|
872
|
+
* Copyright (C) 2025 baxyz
|
|
873
|
+
* SPDX-License-Identifier: LGPL-3.0-or-later
|
|
874
|
+
*/
|
|
875
|
+
/**
|
|
876
|
+
* Removes the value at a dot/bracket-notation path or explicit key array,
|
|
877
|
+
* mutating the object in place. Uses the same path syntax as {@link get}/{@link set}.
|
|
878
|
+
*
|
|
879
|
+
* A missing intermediate segment is a no-op (nothing to remove), not an error.
|
|
880
|
+
* As with `set`, any path containing a string segment equal to `__proto__`,
|
|
881
|
+
* `constructor`, or `prototype` is rejected and the object is returned unchanged.
|
|
882
|
+
*
|
|
883
|
+
* The removed key stops appearing in `Object.keys`/`for...in` — unlike setting
|
|
884
|
+
* it to `undefined`, which would keep the key present.
|
|
885
|
+
*
|
|
886
|
+
* @param obj - The object to mutate
|
|
887
|
+
* @param path - Dot/bracket-notation string, or explicit `PropertyKey[]`
|
|
888
|
+
* @returns The same object reference, with the key removed if it existed
|
|
889
|
+
* @example
|
|
890
|
+
* unset({ a: { b: 1, c: 2 } }, 'a.b')
|
|
891
|
+
* // => { a: { c: 2 } }
|
|
892
|
+
* @example
|
|
893
|
+
* unset({ a: 1 }, 'x.y') // path doesn't exist — no-op
|
|
894
|
+
* // => { a: 1 }
|
|
895
|
+
* @since 3.0.0
|
|
896
|
+
*/
|
|
897
|
+
declare function unset<T extends object>(obj: T, path: string | readonly PropertyKey[]): T;
|
|
898
|
+
|
|
899
|
+
/**
|
|
900
|
+
* This file is part of helpers4.
|
|
901
|
+
* Copyright (C) 2025 baxyz
|
|
902
|
+
* SPDX-License-Identifier: LGPL-3.0-or-later
|
|
903
|
+
*/
|
|
904
|
+
|
|
905
|
+
/**
|
|
906
|
+
* Updates the value at a path by applying a function to its current value,
|
|
907
|
+
* creating intermediate objects as needed. Equivalent to
|
|
908
|
+
* `set(obj, path, updater(get(obj, path)))` in a single call.
|
|
909
|
+
*
|
|
910
|
+
* Uses the same path syntax and type-inference rules as {@link get} and
|
|
911
|
+
* {@link set} — see those for the full behavior (string vs. `PropertyKey[]`
|
|
912
|
+
* paths, prototype-pollution guarding, etc.).
|
|
913
|
+
*
|
|
914
|
+
* @param obj - The object to mutate
|
|
915
|
+
* @param path - Dot/bracket-notation string literal or explicit `PropertyKey[]`
|
|
916
|
+
* @param updater - Called with the current value (`undefined` if the path is
|
|
917
|
+
* absent); its return value is written back at the path
|
|
918
|
+
* @returns The mutated object (same reference, narrowed type)
|
|
919
|
+
* @example
|
|
920
|
+
* update({ count: 1 }, 'count', (n) => (n ?? 0) + 1)
|
|
921
|
+
* // => { count: 2 }
|
|
922
|
+
* @example
|
|
923
|
+
* // Missing intermediate objects are created, just like set()
|
|
924
|
+
* update({}, 'stats.hits', (n: number | undefined) => (n ?? 0) + 1)
|
|
925
|
+
* // => { stats: { hits: 1 } }
|
|
926
|
+
* @since 3.0.0
|
|
927
|
+
*/
|
|
928
|
+
declare function update<T extends object, const P extends string | readonly PropertyKey[], V extends DeepGet<T, ParsePath<P>>>(obj: T, path: P, updater: (current: DeepGet<T, ParsePath<P>> | undefined) => V): string extends P ? T : readonly PropertyKey[] extends P ? T : ContainsUnsafeStringKey<ParsePath<P>> extends true ? T : DeepSet<T, ParsePath<P>, V>;
|
|
929
|
+
|
|
930
|
+
export { clone, cloneDeep, compact, diff, equalsDeep, equalsShallow, flatten, get, groupBy, invert, isEmpty, isNonEmpty, map, mergeDeep, omit, omitBy, parsePropertyPath, pick, pickBy, removeUndefinedNull, safeJsonParse, set, unflatten, unset, update };
|
|
675
931
|
export type { DiffOptions, DiffResult };
|