UNPKG

patched-undo-peasy

Version:
85 lines (74 loc) 2.13 kB
import _ from "lodash"; type ObjOrArray = object | Array<any>; /** Return a copy of an object with some fields elided. * * @param fn copy will not include source properties for which this function returns true */ export function copyFiltered( src: ObjOrArray, fn: (value: any, key: string, path: string[]) => boolean ): ObjOrArray { return filterCopyRecurse(src, []); function filterCopyRecurse(obj: ObjOrArray, path: string[]): ObjOrArray { if (_.isArray(obj)) { return obj.map((elem) => filterCopyRecurse(elem, path)); } if (_.isObject(obj)) { const filtered = Object.entries(obj).filter( ([key, value]) => !fn(value, key, path) ); const copies = filtered.map(([key, value]) => [ key, filterCopyRecurse(value, path.concat([key])), ]); return Object.fromEntries(copies); } return obj; } } /** replace undefined fields with a default value */ export function replaceUndefined<T extends Partial<U>, U>( obj: T, defaults: U ): T & U { const result = { ...defaults, ...removeUndefined(obj) }; return result; } /** @return a copy, eliding fields with undefined values */ export function removeUndefined<T>(obj: T): T { const result = { ...obj }; for (const key in result) { if (result[key] === undefined) { delete result[key]; } } return result; } export interface AnyObject { [key: string]: any; } /** @return the paths of to all getter properties nested in a source object */ export function findGetters( src: AnyObject, pathPrefix: string[] = [] ): string[][] { const result = Object.entries(src).flatMap(([key, value]) => { if (isGetter(src, key)) { const getter = [pathPrefix.concat([key])]; return getter; } else if (_.isPlainObject(value)) { const found = findGetters(value, pathPrefix.concat([key])); return found; } else { return []; } }); return result; } function isGetter(src: {}, key: string): boolean { const desc = Object.getOwnPropertyDescriptor(src, key); if (desc && desc.get) { return true; } return false; }