import { Dictionary } from './types' ; param obj param callbackFn public export function forEach < T extends Dictionary > ( obj , callbackFn ) { if ( obj == null ) { return ; } let index = 0 ; for ( const key in obj ) { if ( Object . prototype . hasOwnProperty . call ( obj , key ) && obj [ key ] !== undefined ) { callbackFn ( key , obj [ key ] , index ++ ) ; } } } param obj param reducer param initialValue returns public export function reduce < T extends Dictionary , V > ( obj , reducer , initialValue ) { let accumulator = initialValue ; forEach ( obj , ( key , value , index ) => { accumulator = reducer ( accumulator , key , value , index ) ; } ) ; return accumulator ; } param obj param mapper returns public export function map < T extends Dictionary , W > ( obj , mapper ) { return reduce ( obj , ( accumulator , key , value , index ) => { accumulator [ key ] = mapper ( key , value , index ) ; return accumulator ; } , { } as Record < keyof T , W > ) ; } param obj returns public export function cleanUndefined < T > ( obj ) { return typeof obj !== 'object' || obj === null || Array . isArray ( obj ) ? obj : reduce ( obj , ( pickedObject , key , value ) => { pickedObject [ key ] = cleanUndefined ( value ) ; return pickedObject ; } , { } as T ) ; } param obj param isIncluded returns public export function objectFilter < T extends Dictionary > ( obj , isIncluded ) { return reduce ( obj , ( accumulator , key , value , index ) => { if ( isIncluded ( key , value , index ) ) { accumulator [ key ] = value ; } return accumulator ; } , { } as T ) ; } param newValue param oldValue returns public export function getNewAndUpdatedKeys < ObjectType extends Dictionary > ( newValue , oldValue ) { if ( newValue === oldValue || ! newValue || ! oldValue ) { return [ ] ; } return Object . keys ( newValue ) . filter ( key => ! ( key in oldValue ) || newValue [ key ] !== oldValue [ key ] ) ; }