@plugjs/plug
Version:
PlugJS Build System ===================
55 lines (45 loc) • 2.4 kB
text/typescript
/** A type extacting string parameters from an arguments array */
export type ParsedParams<Args extends readonly any[]> =
// Normal tuple, we stop processing if the _first_ argument is not a string!
Args extends readonly [ infer First, ...infer Rest ] ?
First extends string ? [ First, ...ParsedParams<Rest> ] : [] :
// If not caught above, here "first" is the rest parameter in the tuple
Args extends readonly [ ...infer First, infer Rest ] ?
Rest extends string ? [ ...ParsedParams<First>, Rest ] : [ ...ParsedParams<First> ] :
// Not a tuple: normal string array or the end of our arguments
Args extends readonly string[] ? [ ...Args ] : []
/** A type extacting the (last) options type from an arguments array */
export type ParsedOptions<Args extends readonly any[]> = // , Defaults> =
Args extends readonly [ ...string[], infer Last ] ?
Last extends object ? // Record<any, any> ?
Last : // last arg is a record, defaults is null or undefined
never : // last arg is a string, defaults is null or undefined
never // args is not an array
/** Parserable arguments: a number of strings, followed by optional options */
export type ParseOptions<Options extends Record<any, any>> =
readonly [ ...params: string[] ] | readonly [ ...params: string[], options: Options ]
/** The return type from {@link ParseOptions} */
export interface ParsedResult<Args extends readonly any [], Options, Defaults> {
params: ParsedParams<Args>,
options: Defaults extends null | undefined ? Options | undefined : Options & Defaults
}
/**
* Parse an array of arguments (a number of strings optionally followed by an
* options object into parameters and options.
*/
export function parseOptions<
Args extends ParseOptions<any>,
Options extends ParsedOptions<Args> = ParsedOptions<Args>,
Defaults extends ParsedOptions<Args> | null | undefined = undefined,
>(args: Args, defaults?: Defaults): ParsedResult<Args, Options, Defaults> {
const params: string[] = []
const clone: any[] = [ ...args ]
// Collect all strings at the beginning of our arguments array
while (typeof clone[0] === 'string') {
params.push(clone.shift())
}
// The options is the _last_ element in our arguments array (if any)
const options = Object.assign({}, defaults, clone.pop())
// All done
return { params, options } as ParsedResult<Args, Options, Defaults>
}