export type ResourceKey < TKey > = TKey | ResourceKeyList < TKey > ; export type SingleResourceKey < T > = Exclude < T , Exclude < T , ResourceKeyList < any > > > extends ResourceKeyList < infer TKey > ? TKey : T ; export class ResourceKeyList < TKey > { readonly list : TKey [ ] ; readonly mark : any ; constructor ( list , mark ? ) { this . list = Array . isArray ( list ) ? list : [ list ] ; this . mark = mark ; } includes ( key ) { if ( isResourceKeyList ( key ) ) { return key . list . some ( key => this . list . includes ( key ) ) ; } return this . list . includes ( key ) ; } } interface MapFnc { < TKey , TValue > ( key , selector ) : TValue [ ] ; < TKey , TValue > ( key , selector ) : TKey extends ResourceKeyList < any > ? TValue [ ] : TValue ; } export interface ResourceKeyUtils { hasMark : < TKey > ( key : ResourceKey < TKey > , mark : any ) => boolean ; count : < TKey > ( key : ResourceKey < TKey > ) => number ; first : < TKey > ( key : ResourceKey < TKey > ) => TKey ; forEach : < TKey > ( key : ResourceKey < TKey > , action : ( key : TKey , index : number ) => any ) => void ; forEachAsync : < TKey > ( key : ResourceKey < TKey > , action : ( key : TKey , index : number ) => Promise < any > ) => Promise < void > ; some : < TKey > ( key : ResourceKey < TKey > , predicate : ( key : TKey , index : number ) => boolean ) => boolean ; every : < TKey > ( key : ResourceKey < TKey > , predicate : ( key : TKey , index : number ) => boolean ) => boolean ; map : MapFnc ; includes : < TKey > ( first : ResourceKey < TKey > , second : ResourceKey < TKey > ) => boolean ; exclude : < TKey > ( first : ResourceKeyList < TKey > , second : ResourceKey < TKey > ) => ResourceKeyList < TKey > ; join : < TKey > ( ... keys : Array < ResourceKey < TKey > > ) => ResourceKeyList < TKey > ; add : < TKey > ( key : ResourceKey < TKey > , ... elements : TKey [ ] ) => ResourceKeyList < TKey > ; } export const ResourceKeyUtils = { hasMark < TKey > ( key , mark ) { if ( isResourceKeyList ( key ) ) { return key . mark === mark ; } else { return false ; } } , count < TKey > ( key ) { if ( isResourceKeyList ( key ) ) { return key . list . length ; } else { return 0 ; } } , first < TKey > ( key ) { if ( isResourceKeyList ( key ) ) { return key . list [ 0 ] ; } else { return key ; } } , forEach < TKey > ( key , action ) { if ( isResourceKeyList ( key ) ) { for ( let i = 0 ; i < key . list . length ; i ++ ) { action ( key . list [ i ] , i ) ; } } else { action ( key , - 1 ) ; } } , async forEachAsync < TKey > ( key , action ) { if ( isResourceKeyList ( key ) ) { for ( let i = 0 ; i < key . list . length ; i ++ ) { await action ( key . list [ i ] , i ) ; } } else { await action ( key , - 1 ) ; } } , some < TKey > ( key , predicate ) { if ( isResourceKeyList ( key ) ) { return key . list . some ( predicate ) ; } else { return predicate ( key , - 1 ) ; } } , every < TKey > ( key , predicate ) { if ( isResourceKeyList ( key ) ) { return key . list . every ( predicate ) ; } else { return predicate ( key , - 1 ) ; } } , map < TKey , TValue > ( key , selector ) { if ( isResourceKeyList ( key ) ) { return key . list . map ( selector ) ; } else { return selector ( key , - 1 ) ; } } , includes < TKey > ( param , key ) { if ( isResourceKeyList ( param ) ) { return param . includes ( key ) ; } if ( isResourceKeyList ( key ) ) { return key . includes ( param ) ; } return param === key ; } , exclude < TKey > ( param , key ) { if ( isResourceKeyList ( key ) ) { return resourceKeyList ( param . list . filter ( param => ! key . list . includes ( param ) ) , param . mark ) ; } return resourceKeyList ( param . list . filter ( param => param !== key ) , param . mark ) ; } , join < TKey > ( ... keys ) { const list = [ ] ; for ( const param of keys ) { if ( isResourceKeyList ( param ) ) { list . push ( ... param . list ) ; } else { list . push ( param ) ; } } return resourceKeyList ( list ) ; } , add < TKey > ( key , ... elements ) { const list = [ ] ; if ( isResourceKeyList ( key ) ) { list . push ( ... key . list ) ; } else { list . push ( key ) ; } list . push ( ... elements ) ; return resourceKeyList ( list ) ; } , } ; export function isResourceKeyList < T > ( data ) { return data instanceof ResourceKeyList ; } export function resourceKeyList < T > ( list , mark ? ) { return new ResourceKeyList ( list , mark ) ; }