-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
recursivePick.ts
37 lines (36 loc) · 1.23 KB
/
recursivePick.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
import { isPlainObject } from 'is-what'
import pathsAreEqual from './pathsAreEqual.js'
export function recursivePick<T extends Record<string, any>, PickedKeys extends string[]>(
obj: T,
pickedKeys: PickedKeys,
pathUntilNow = ''
): T {
if (!isPlainObject(obj)) {
return obj
}
return Object.entries(obj).reduce<Record<string, any>>((carry, [key, value]) => {
let path = pathUntilNow
if (path) path += '.'
path += key
// check pickedKeys up to this point
if (pickedKeys.length) {
let passed = false
pickedKeys.forEach((pickedKey) => {
const pathDepth = path.split('.').length
const pickedKeyDepth = pickedKey.split('.').length
const pickedKeyUpToNow = pickedKey.split('.').slice(0, pathDepth).join('.')
const pathUpToPickedKeyDepth = path.split('.').slice(0, pickedKeyDepth).join('.')
if (pathsAreEqual(pathUpToPickedKeyDepth, pickedKeyUpToNow)) passed = true
})
// there's not one pickedKey that allows up to now
if (!passed) return carry
}
// no further recursion needed
if (!isPlainObject(value)) {
carry[key] = value
return carry
}
carry[key] = recursivePick(obj[key], pickedKeys, path)
return carry
}, {}) as T
}