export type Flag < T , N extends string > = ( args : string [ ] ) => ParseResult < T , N > ; export type ParseResult < T , N extends string > = { [ key in N ] : { value ? : T ; option : FlagOption < T > ; position ? : number [ ] ; } ; } ; export type NumberFlag < N extends string > = Flag < number , N > ; export type StringFlag < N extends string > = Flag < string , N > ; export type BooleanFlag < N extends string > = Flag < boolean , N > ; export type FlagOption < T > = { alias ? : string ; default ? : T ; usage ? : string ; } ; function findIndex ( args , ... names ) { return args . findIndex ( a => { const result = names . findIndex ( n => { return a === `--${ n }` || a === `-${ n }` ; } ) ; return result > - 1 ; } ) ; } export function makeNumberFlag < N extends string > ( name , option = { } ) { return ( args ) => { const idx = findIndex ( args , name , option . alias || "" ) ; if ( idx < 0 || idx + 1 >= args . length ) { return < any > { [ name ] : { value : option . default , option } } ; } const v = args [ idx + 1 ] ; return < any > { [ name ] : { value : parseInt ( v , 10 ) , option , position : [ idx , idx + 1 ] } } ; } ; } export function makeStringFlag < N extends string > ( name , option = { } ) { return ( args ) => { const idx = findIndex ( args , name , option . alias ) ; if ( idx < 0 || idx + 1 >= args . length ) { return < any > { [ name ] : { value : option . default , option } } ; } const v = args [ idx + 1 ] ; return < any > { [ name ] : { value : v , option , position : v ? [ idx , idx + 1 ] : undefined } } ; } ; } export function makeBooleanFlag < N extends string > ( name , option = { } ) { return ( args ) => { const idx = findIndex ( args , name , option . alias ) ; if ( idx < 0 ) { return < any > { [ name ] : { value : option . default , option } } ; } return < any > { [ name ] : { value : true , option , position : [ idx ] } } ; } ; } export type TupleTypes < T > = { [ P in keyof T ] : T [ P ] ; } extends { [ key ] : ( args : any ) => infer V ; } ? V : never ; export type UnionToIntersection < U > = ( U extends any ? ( k : U ) => void : never ) extends ( ( k : infer I ) => void ) ? I : never ; export function reduceFlag < T extends Array < ( args : string [ ] ) => { [ key ] : any ; } > > ( ... src ) { return < any > src . splice ( 1 ) . reduce ( ( acc , cur ) => { return _compose ( acc , cur ) ; } , src [ 0 ] ) ; } function _compose < T1 , T1Name extends string , T2 , T2Name extends string > ( t1 , t2 ) { return ( args ) => { const t1v = t1 ( args ) ; const t2v = t2 ( args ) ; return < any > { ... t1v , ... t2v } ; } ; }