const { hasOwnProperty } = Object . prototype ; export function mergeProps ( propObjs , complexPropsMap ? ) { let dest = { } ; if ( complexPropsMap ) { for ( let name in complexPropsMap ) { let complexObjs = [ ] ; for ( let i = propObjs . length - 1 ; i >= 0 ; i -= 1 ) { let val = propObjs [ i ] [ name ] ; if ( typeof val === 'object' && val ) { complexObjs . unshift ( val ) ; } else if ( val !== undefined ) { dest [ name ] = val ; break ; } } if ( complexObjs . length ) { dest [ name ] = mergeProps ( complexObjs ) ; } } } for ( let i = propObjs . length - 1 ; i >= 0 ; i -= 1 ) { let props = propObjs [ i ] ; for ( let name in props ) { if ( ! ( name in dest ) ) { dest [ name ] = props [ name ] ; } } } return dest ; } export function filterHash ( hash , func ) { let filtered = { } ; for ( let key in hash ) { if ( func ( hash [ key ] , key ) ) { filtered [ key ] = hash [ key ] ; } } return filtered ; } export function mapHash < InputItem , OutputItem > ( hash , func ) { let newHash = { } ; for ( let key in hash ) { newHash [ key ] = func ( hash [ key ] , key ) ; } return newHash ; } export function arrayToHash ( a ) { let hash = { } ; for ( let item of a ) { hash [ item ] = true ; } return hash ; } export function buildHashFromArray < Item , ItemRes > ( a , func ) { let hash = { } ; for ( let i = 0 ; i < a . length ; i += 1 ) { let tuple = func ( a [ i ] , i ) ; hash [ tuple [ 0 ] ] = tuple [ 1 ] ; } return hash ; } export function hashValuesToArray ( obj ) { let a = [ ] ; for ( let key in obj ) { a . push ( obj [ key ] ) ; } return a ; } export function isPropsEqual ( obj0 , obj1 ) { if ( obj0 === obj1 ) { return true ; } for ( let key in obj0 ) { if ( hasOwnProperty . call ( obj0 , key ) ) { if ( ! ( key in obj1 ) ) { return false ; } } } for ( let key in obj1 ) { if ( hasOwnProperty . call ( obj1 , key ) ) { if ( obj0 [ key ] !== obj1 [ key ] ) { return false ; } } } return true ; } export function getUnequalProps ( obj0 , obj1 ) { let keys = [ ] ; for ( let key in obj0 ) { if ( hasOwnProperty . call ( obj0 , key ) ) { if ( ! ( key in obj1 ) ) { keys . push ( key ) ; } } } for ( let key in obj1 ) { if ( hasOwnProperty . call ( obj1 , key ) ) { if ( obj0 [ key ] !== obj1 [ key ] ) { keys . push ( key ) ; } } } return keys ; } export type EqualityFunc < T > = ( a : T , b : T ) => boolean ; export type EqualityThing < T > = EqualityFunc < T > | true ; export type EqualityFuncs < ObjType > = { [ K in keyof ObjType ] ? : EqualityThing < ObjType [ K ] > ; } ; export function compareObjs ( oldProps , newProps , equalityFuncs = { } ) { if ( oldProps === newProps ) { return true ; } for ( let key in newProps ) { if ( key in oldProps && isObjValsEqual ( oldProps [ key ] , newProps [ key ] , equalityFuncs [ key ] ) ) { } else { return false ; } } for ( let key in oldProps ) { if ( ! ( key in newProps ) ) { return false ; } } return true ; } function isObjValsEqual < T > ( val0 , val1 , comparator ) { if ( val0 === val1 || comparator === true ) { return true ; } if ( comparator ) { return comparator ( val0 , val1 ) ; } return false ; } export function collectFromHash < Item > ( hash , startIndex = 0 , endIndex ? , step = 1 ) { let res = [ ] ; if ( endIndex == null ) { endIndex = Object . keys ( hash ) . length ; } for ( let i = startIndex ; i < endIndex ; i += step ) { let val = hash [ i ] ; if ( val !== undefined ) { res . push ( val ) ; } } return res ; }