import { ChartSizeInput } from '@t/options' ; type PickedKey < T , K extends keyof T > = keyof Pick < T , K > ; type OmittedKey < T , K extends keyof T > = keyof Omit < T , K > ; export function isExist ( value ) { return ! isUndefined ( value ) && ! isNull ( value ) ; } export function isDate ( value ) { return value instanceof Date ; } export function isUndefined ( value ) { return typeof value === 'undefined' ; } export function isNull ( value ) { return value === null ; } export function isBoolean ( value ) { return typeof value === 'boolean' ; } export function isNumber ( value ) { return typeof value === 'number' ; } export function isString ( value ) { return typeof value === 'string' ; } export function isInteger ( value ) { return isNumber ( value ) && isFinite ( value ) && Math . floor ( value ) === value ; } export function isObject ( obj ) { return typeof obj === 'object' && obj !== null ; } export function isFunction ( value ) { return typeof value === 'function' ; } export function forEach < T extends object , K extends Extract < keyof T , string > , V extends T [ K ] > ( obj , cb ) { for ( const key in obj ) { if ( obj . hasOwnProperty ( key ) ) { cb ( obj [ key as K ] as V , key as K ) ; } } } export function forEachArray < T > ( arr , iteratee , context = null ) { for ( let index = 0 , len = arr . length ; index < len ; index += 1 ) { if ( iteratee . call ( context , arr [ index ] , index , arr ) === false ) { break ; } } } export function range ( start , stop ? , step ? ) { if ( isUndefined ( stop ) ) { stop = start || 0 ; start = 0 ; } step = step || 1 ; const arr = [ ] ; if ( stop ) { const flag = step < 0 ? - 1 : 1 ; stop *= flag ; for ( ; start * flag < stop ; start += step ) { arr . push ( start ) ; } } return arr ; } export function toArray < T > ( arrayLike ) { let arr = [ ] ; try { arr = Array . prototype . slice . call ( arrayLike ) ; } catch ( e ) { forEachArray ( arrayLike , function ( value ) { arr . push ( value ) ; } ) ; } return arr ; } export function includes < T > ( arr , searchItem , searchIndex ? ) { if ( typeof searchIndex === 'number' && arr [ searchIndex ] !== searchItem ) { return false ; } for ( const item of arr ) { if ( item === searchItem ) { return true ; } } return false ; } export function pick < T extends object , K extends keyof T > ( obj , ... propNames ) { const resultMap = { } as Pick < T , K > ; Object . keys ( obj ) . forEach ( ( key ) => { if ( includes ( propNames , key as K ) ) { resultMap [ key as PickedKey < T , K > ] = obj [ key as PickedKey < T , K > ] ; } } ) ; return resultMap ; } export function omit < T extends object , K extends keyof T > ( obj , ... propNames ) { const resultMap = { } as Omit < T , K > ; Object . keys ( obj ) . forEach ( ( key ) => { if ( ! includes ( propNames , key as K ) ) { resultMap [ key as OmittedKey < T , K > ] = obj [ key as OmittedKey < T , K > ] ; } } ) ; return resultMap ; } export function pickProperty ( target , keys ) { const { length } = keys ; if ( length ) { for ( let i = 0 ; i < length ; i += 1 ) { if ( isUndefined ( target ) || isNull ( target ) ) { return null ; } target = target [ keys [ i ] ] ; } } return target ; } export function pickPropertyWithMakeup ( target , args ) { const { length } = args ; if ( length ) { for ( let i = 0 ; i < length ; i += 1 ) { if ( isUndefined ( target [ args [ i ] ] ) ) { target [ args [ i ] ] = { } ; } target = target [ args [ i ] ] ; } } return target ; } export function debounce ( fn , delay = 0 ) { let timer ; function debounced ( ... args ) { window . clearTimeout ( timer ) ; timer = window . setTimeout ( ( ) => { fn ( ... args ) ; } , delay ) ; } return debounced ; } export function merge ( target , ... args ) { target = target || { } ; args . forEach ( ( obj ) => { if ( ! obj ) { return ; } forEach ( obj , ( item , key ) => { if ( Object . prototype . toString . call ( item ) === '[object Object]' ) { target [ key ] = merge ( target [ key ] , item ) ; } else { target [ key ] = item ; } } ) ; } ) ; return target ; } export function throttle ( fn , interval = 0 ) { let base = null ; let isLeading = true ; const tick = function ( ... args ) { fn ( ... args ) ; base = null ; } ; let stamp = 0 ; const debounced = debounce ( tick , interval ) ; function throttled ( ... args ) { if ( isLeading ) { tick ( ... args ) ; isLeading = false ; return ; } stamp = Number ( new Date ( ) ) ; base = base || stamp ; debounced ( args ) ; if ( stamp - base >= interval ) { tick ( args ) ; } } function reset ( ) { isLeading = true ; base = null ; } throttled . reset = reset ; return throttled ; } export function deepMergedCopy < T1 extends Record < string , any > , T2 extends Record < string , any > > ( targetObj , obj ) { const resultObj = { ... targetObj } as T1 & T2 ; Object . keys ( obj ) . forEach ( ( prop ) => { if ( isObject ( resultObj [ prop ] ) ) { if ( Array . isArray ( obj [ prop ] ) ) { resultObj [ prop as keyof T1 & T2 ] = deepCopyArray ( obj [ prop ] ) ; } else if ( resultObj . hasOwnProperty ( prop ) ) { resultObj [ prop ] = deepMergedCopy ( resultObj [ prop ] , obj [ prop ] ) ; } else { resultObj [ prop as keyof T1 & T2 ] = deepCopy ( obj [ prop ] ) ; } } else { resultObj [ prop as keyof T1 & T2 ] = obj [ prop ] ; } } ) ; return resultObj ; } export function deepCopyArray < T extends Array < any > > ( items ) { return items . map ( ( item ) => { if ( isObject ( item ) ) { return Array . isArray ( item ) ? deepCopyArray ( item ) : deepCopy ( item ) ; } return item ; } ) as T ; } export function deepCopy < T extends Record < string , any > > ( obj ) { const resultObj = { } as T ; const keys = Object . keys ( obj ) ; if ( ! keys . length ) { return obj ; } keys . forEach ( ( prop ) => { if ( isObject ( obj [ prop ] ) ) { resultObj [ prop ] = Array . isArray ( obj [ prop ] ) ? deepCopyArray ( obj [ prop ] ) : deepCopy ( obj [ prop ] ) ; } else { resultObj [ prop ] = obj [ prop ] ; } } ) ; return resultObj as T ; } export function sortCategories ( x , y ) { return isInteger ( x ) ? Number ( x ) - Number ( y ) : new Date ( x ) . getTime ( ) - new Date ( y ) . getTime ( ) ; } export function sortNumber ( x , y ) { return x - y ; } export function first < T > ( items ) { return items . length ? items [ 0 ] : undefined ; } export function last < T > ( items ) { return items . length ? items [ items . length - 1 ] : undefined ; } export function hasNegative ( values = [ ] ) { return values . some ( ( value ) => Number ( value ) < 0 ) ; } export function sum ( items ) { return items . reduce ( ( a , b ) => a + b , 0 ) ; } export function hasPositiveOnly ( values ) { return values . every ( ( value ) => Number ( value ) >= 0 ) ; } export function hasNegativeOnly ( values ) { return values . every ( ( value ) => Number ( value ) <= 0 ) ; } export function getFirstValidValue ( values ) { return values ?. find ( ( value ) => value !== null ) ; } export function getPercentageValue ( text ) { return Number ( text . substr ( 0 , text . length - 1 ) ) ; } export function calculateSizeWithPercentString ( size , value ) { return isNumber ( value ) ? value : Number ( ( ( size * getPercentageValue ( value ) ) / 100 ) . toFixed ( 2 ) ) ; } export function getInitialSize ( size ? ) { return isNumber ( size ) ? size : 0 ; } export function isAutoValue ( value ? ) { return value === 'auto' ; }