-
Notifications
You must be signed in to change notification settings - Fork 7
/
assocPath.ts
76 lines (61 loc) · 2.36 KB
/
assocPath.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
// Copyright (c) 2020 Jozty. All rights reserved. MIT license.
import { getPath, Path } from './paths.ts';
import { tail } from './tail.ts';
import { assoc } from './assoc.ts';
import has from './utils/has.ts';
import { isArray, isInteger, isNotUndefinedOrNull } from './utils/is.ts';
import curryN from './utils/curry_n.ts';
import type { ObjRec, PH } from './utils/types.ts';
// @types
type AssocPath_1 = (path: Path) => ObjRec;
type AssocPath_2 = (val: unknown) => ObjRec;
type AssocPath_3 = (obj: ObjRec) => ObjRec;
type AssocPath_2_3 =
& ((val: unknown) => AssocPath_3)
& ((val: PH, obj: ObjRec) => AssocPath_2)
& ((val: unknown, obj: ObjRec) => ObjRec);
type AssocPath_1_3 =
& ((path: Path) => AssocPath_3)
& ((path: PH, obj: ObjRec) => AssocPath_1)
& ((path: Path, obj: ObjRec) => ObjRec);
type AssocPath_1_2 =
& ((path: Path) => AssocPath_2)
& ((path: PH, val: unknown) => AssocPath_1)
& ((path: Path, val: unknown) => ObjRec);
type AssocPath =
& ((path: Path) => AssocPath_2_3)
& ((path: PH, val: unknown) => AssocPath_1_3)
& ((path: PH, val: PH, obj: ObjRec) => AssocPath_1_2)
& ((path: Path, val: unknown) => AssocPath_3)
& ((path: Path, val: PH, obj: ObjRec) => AssocPath_2)
& ((path: PH, val: unknown, obj: ObjRec) => AssocPath_1)
& ((path: Path, val: unknown, obj: ObjRec) => ObjRec);
function _assocPath(path: Path, val: unknown, obj: ObjRec) {
if (path.length === 0) return val;
const p = getPath(path);
const prop = p[0];
if (p.length > 1) {
const child = isNotUndefinedOrNull(obj) && has(obj, prop)
? obj[prop]
: isInteger(prop)
? []
: {};
val = _assocPath(tail(p) as Path, val, child as ObjRec);
}
if (isInteger(prop) && isArray(obj)) {
const result: unknown[] = [...obj];
result[prop] = val;
return result;
}
return assoc(prop, val, obj);
}
/**
* Makes a shallow clone of an object, setting or overriding the nodes required
* to create the given path, and placing the specific value at the tail end of
* that path. Note that this copies and flattens prototype properties onto the
* new object as well. All non-primitive properties are copied by reference.
*
* Fae.assocPath(['a', 'b', 'c'], 42, {a: {b: {c: 0}}}); //=> {a: {b: {c: 42}}}
* Fae.assocPath(['a', 'b', 'c'], 42, {a: 5}); //=> {a: {b: {c: 42}}}
*/
export const assocPath = curryN(3, _assocPath) as AssocPath;