/** A type extacting string parameters from an arguments array */ export type ParsedParams = // 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 ] : [] : // If not caught above, here "first" is the rest parameter in the tuple Args extends readonly [ ...infer First, infer Rest ] ? Rest extends string ? [ ...ParsedParams, Rest ] : [ ...ParsedParams ] : // 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 = // , Defaults> = Args extends readonly [ ...string[], infer Last ] ? Last extends object ? // Record ? 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> = readonly [ ...params: string[] ] | readonly [ ...params: string[], options: Options ] /** The return type from {@link ParseOptions} */ export interface ParsedResult { params: ParsedParams, 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, Options extends ParsedOptions = ParsedOptions, Defaults extends ParsedOptions | null | undefined = undefined, >(args: Args, defaults?: Defaults): ParsedResult { 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 }