103 lines
2.5 KiB
TypeScript
103 lines
2.5 KiB
TypeScript
import {
|
|
cloneDeep,
|
|
isArray,
|
|
isBoolean,
|
|
isNull,
|
|
isNumber,
|
|
isObject,
|
|
isString,
|
|
isUndefined,
|
|
} from "lodash"
|
|
|
|
export type Path =
|
|
| string
|
|
| {
|
|
[key: string]: (string | Path)[]
|
|
}
|
|
|
|
/*
|
|
Usage:
|
|
const object = {
|
|
a: 1,
|
|
b: 2,
|
|
c: {
|
|
d: 4,
|
|
f: 5,
|
|
},
|
|
g: [
|
|
{
|
|
h: 6,
|
|
i: 7,
|
|
},
|
|
{
|
|
h: 8,
|
|
i: 9,
|
|
}
|
|
],
|
|
}
|
|
|
|
const picked = deepPick(object, ["a", { c: ["d"] }, { g: ["h"] }]);
|
|
console.log(picked); // Output: { a: 1, c: { d: 4 }, g: [{ h: 6 }, { h: 8 }] }
|
|
|
|
TODO: figure out how to do this without "any"
|
|
*/
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
export function deepPick(object: any, paths: Path[]): any {
|
|
if (isArray(object)) {
|
|
return object.map((item) => deepPick(item, paths))
|
|
}
|
|
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
return paths.reduce((result: any, path: Path) => {
|
|
if (isString(path)) {
|
|
if (path in object === false) return result
|
|
|
|
const value = cloneDeep(object[path])
|
|
if (isSimpleType(value)) {
|
|
result[path] = value
|
|
return result
|
|
} else if (isArray(value) && value.every(isSimpleType)) {
|
|
result[path] = value
|
|
return result
|
|
} else if (isArray(value) && value.every(isObject)) {
|
|
result[path] = []
|
|
return result
|
|
} else if (isObject(value)) {
|
|
result[path] = value
|
|
return result
|
|
} else {
|
|
throw new Error(`Unsupported value type at path: ${path} -> ${JSON.stringify(value)}`)
|
|
}
|
|
} else if (isObject(path)) {
|
|
Object.entries(path).forEach(([path, nestedPaths]) => {
|
|
if (path in object === false) return
|
|
|
|
const value = cloneDeep(object[path])
|
|
if (isSimpleType(value)) {
|
|
result[path] = value
|
|
} else if (isArray(value) && value.every(isSimpleType)) {
|
|
result[path] = value
|
|
} else if (Array.isArray(value) && value.every(isObject)) {
|
|
result[path] = value.map((item) => deepPick(item, nestedPaths))
|
|
} else if (isObject(value)) {
|
|
result[path] = deepPick(value, nestedPaths)
|
|
} else {
|
|
throw new Error(
|
|
`Unsupported value structure at path: ${path} -> ${JSON.stringify(value)}`
|
|
)
|
|
}
|
|
})
|
|
|
|
return result
|
|
} else {
|
|
throw new Error(`Unsupported path type: ${path}`)
|
|
}
|
|
}, {})
|
|
}
|
|
|
|
function isSimpleType(value: unknown) {
|
|
return (
|
|
isString(value) || isNumber(value) || isBoolean(value) || isNull(value) || isUndefined(value)
|
|
)
|
|
}
|