type Group < T > = Record < string , T [ ] > ; public export type GroupByKeyFn < T > = ( data : T ) => string ; public export type GroupKeysOrKeyFn < T > = Array < keyof T > | GroupByKeyFn < T > ; internal export function groupBy < T > ( data , keysOrKeyFn , asArray ) ; internal export function groupBy < T > ( data , keysOrKeyFn , asArray ) ; internal export function groupBy < T > ( data , keysOrKeyFn , asArray ) { const keyFn = Array . isArray ( keysOrKeyFn ) ? getUniqueKey ( keysOrKeyFn ) : keysOrKeyFn ; const grouped = data . reduce < Group < T > > ( ( acc , curr ) => { const key = keyFn ( curr ) ; if ( ! acc [ key ] ) { acc [ key ] = [ ] ; } acc [ key ] . push ( curr ) ; return acc ; } , { } ) ; return asArray ? Object . values ( grouped ) : grouped ; } internal export function getUniqueKey < T > ( keys , concat = '|' ) { return ( data ) : string => { return keys . map ( ( key ) => { return data [ key ] ; } ) . join ( concat ) ; } ; }