export type CollectionPredicate = ( item ? : any , index ? : number , collection ? : any [ ] ) => boolean ; export function isUndefined ( value ) { return typeof value === 'undefined' ; } export function isNull ( value ) { return value === null ; } export function isNumber ( value ) { return typeof value === 'number' ; } export function isNumberFinite ( value ) { return isNumber ( value ) && isFinite ( value ) ; } export function isPositive ( value ) { return value >= 0 ; } export function isInteger ( value ) { return value % 1 === 0 ; } export function isNil ( value ) { return value === null || typeof value === 'undefined' ; } export function isString ( value ) { return typeof value === 'string' ; } export function isObject ( value ) { return value !== null && typeof value === 'object' ; } export function isArray ( value ) { return Array . isArray ( value ) ; } export function isFunction ( value ) { return typeof value === 'function' ; } export function toDecimal ( value , decimal ) { return Math . round ( value * Math . pow ( 10 , decimal ) ) / Math . pow ( 10 , decimal ) ; } export function upperFirst ( value ) { return value . slice ( 0 , 1 ) . toUpperCase ( ) + value . slice ( 1 ) ; } export function createRound ( method ) { const func = ( < any > Math ) [ method ] ; return function ( value , precision = 0 ) { if ( typeof value === 'string' ) { throw new TypeError ( 'Rounding method needs a number' ) ; } if ( typeof precision !== 'number' || isNaN ( precision ) ) { precision = 0 ; } if ( precision ) { let pair = `${ value }e` . split ( 'e' ) ; const val = func ( `${ pair [ 0 ] }e` + ( + pair [ 1 ] + precision ) ) ; pair = `${ val }e` . split ( 'e' ) ; return + ( pair [ 0 ] + 'e' + ( + pair [ 1 ] - precision ) ) ; } return func ( value ) ; } ; } export function leftPad ( str , len = 0 , ch = ' ' ) { str = String ( str ) ; ch = toString ( ch ) ; let i = - 1 ; const length = len - str . length ; while ( ++ i < length && str . length + ch . length <= len ) { str = ch + str ; } return str ; } export function rightPad ( str , len = 0 , ch = ' ' ) { str = String ( str ) ; ch = toString ( ch ) ; let i = - 1 ; const length = len - str . length ; while ( ++ i < length && str . length + ch . length <= len ) { str += ch ; } return str ; } export function toString ( value ) { return `${ value }` ; } export function pad ( str , len = 0 , ch = ' ' ) { str = String ( str ) ; ch = toString ( ch ) ; let i = - 1 ; const length = len - str . length ; let left = true ; while ( ++ i < length ) { const l = str . length + ch . length <= len ? str . length + ch . length : str . length + 1 ; if ( left ) { str = leftPad ( str , l , ch ) ; } else { str = rightPad ( str , l , ch ) ; } left = ! left ; } return str ; } export function flatten ( input , index = 0 ) { if ( index >= input . length ) { return input ; } if ( isArray ( input [ index ] ) ) { return flatten ( input . slice ( 0 , index ) . concat ( input [ index ] , input . slice ( index + 1 ) ) , index ) ; } return flatten ( input , index + 1 ) ; } export function getProperty ( value , key ) { if ( isNil ( value ) || ! isObject ( value ) ) { return undefined ; } const keys = key . split ( '.' ) ; let result = value [ keys . shift ( ) ! ] ; for ( const key of keys ) { if ( isNil ( result ) || ! isObject ( result ) ) { return undefined ; } result = result [ key ] ; } return result ; } export function sum ( input , initial = 0 ) { return input . reduce ( ( previous , current ) => previous + current , initial ) ; } export function shuffle ( input ) { if ( ! isArray ( input ) ) { return input ; } const copy = [ ... input ] ; for ( let i = copy . length ; i ; -- i ) { const j = Math . floor ( Math . random ( ) * i ) ; const x = copy [ i - 1 ] ; copy [ i - 1 ] = copy [ j ] ; copy [ j ] = x ; } return copy ; } export function deepIndexOf ( collection , value ) { let index = - 1 ; const length = collection . length ; while ( ++ index < length ) { if ( deepEqual ( value , collection [ index ] ) ) { return index ; } } return - 1 ; } export function deepEqual ( a , b ) { if ( a === b ) { return true ; } if ( ! ( typeof a === 'object' && typeof b === 'object' ) ) { return a === b ; } const keysA = Object . keys ( a ) ; const keysB = Object . keys ( b ) ; if ( keysA . length !== keysB . length ) { return false ; } var hasOwn = Object . prototype . hasOwnProperty ; for ( let i = 0 ; i < keysA . length ; i ++ ) { const key = keysA [ i ] ; if ( ! hasOwn . call ( b , keysA [ i ] ) || ! deepEqual ( a [ key ] , b [ key ] ) ) { return false ; } } return true ; } export function isDeepObject ( object ) { return object . __isDeepObject__ ; } export function wrapDeep ( object ) { return new DeepWrapper ( object ) ; } export function unwrapDeep ( object ) { if ( isDeepObject ( object ) ) { return object . data ; } return object ; } export class DeepWrapper { public __isDeepObject__ : boolean = true ; constructor ( public data ) { } } export function count ( input ) { if ( ! isArray ( input ) && ! isObject ( input ) && ! isString ( input ) ) { return input ; } if ( isObject ( input ) ) { return Object . keys ( input ) . map ( value => input [ value ] ) . length ; } return input . length ; } export function empty ( input ) { if ( ! isArray ( input ) ) { return input ; } return input . length === 0 ; } export function every ( input , predicate ) { if ( ! isArray ( input ) || ! predicate ) { return input ; } let result = true ; let i = - 1 ; while ( ++ i < input . length && result ) { result = predicate ( input [ i ] , i , input ) ; } return result ; } export function takeUntil ( input , predicate ) { let i = - 1 ; const result = [ ] ; while ( ++ i < input . length && ! predicate ( input [ i ] , i , input ) ) { result [ i ] = input [ i ] ; } return result ; } export function takeWhile ( input , predicate ) { return takeUntil ( input , ( item , index , collection ) => ! predicate ( item , index , collection ) ) ; }