Merge pull request #32349 from steffenvv/command-improvements

yargs: Improved backwards compatibility and inferred positional option types
This commit is contained in:
Benjamin Lichtman
2019-01-22 09:31:24 -08:00
committed by GitHub
2 changed files with 85 additions and 6 deletions
+7 -6
View File
@@ -176,7 +176,8 @@ declare namespace yargs {
* 'positional' should be called in a command's builder function, and is not
* available on the top-level yargs instance. If so, it will throw an error.
*/
positional(key: string, opt: PositionalOptions): Argv<T>;
positional<K extends keyof T, O extends PositionalOptions>(key: K, opt: O): Argv<Omit<T, K> & { [key in K]: InferredOptionType<O> }>;
positional<K extends string, O extends PositionalOptions>(key: K, opt: O): Argv<T & { [key in K]: InferredOptionType<O> }>;
recommendCommands(): Argv<T>;
@@ -252,7 +253,7 @@ declare namespace yargs {
wrap(columns: number | null): Argv<T>;
}
type Arguments<T> = T & {
type Arguments<T = {}> = T & {
/** Non-option arguments */
_: string[];
/** The script name or node command */
@@ -376,7 +377,7 @@ declare namespace yargs {
type InferredOptionTypes<O extends { [key: string]: Options }> = { [key in keyof O]: InferredOptionType<O[key]> };
interface CommandModule<T, U> {
interface CommandModule<T = {}, U = {}> {
aliases?: ReadonlyArray<string> | string;
builder?: CommandBuilder<T, U>;
command?: ReadonlyArray<string> | string;
@@ -384,11 +385,11 @@ declare namespace yargs {
handler: (args: Arguments<U>) => void;
}
type ParseCallback<T> = (err: Error | undefined, argv: Arguments<T>, output: string) => void;
type CommandBuilder<T, U> = { [key: string]: Options } | ((args: Argv<T>) => Argv<U>);
type ParseCallback<T = {}> = (err: Error | undefined, argv: Arguments<T>, output: string) => void;
type CommandBuilder<T = {}, U = {}> = { [key: string]: Options } | ((args: Argv<T>) => Argv<U>);
type SyncCompletionFunction = (current: string, argv: any) => string[];
type AsyncCompletionFunction = (current: string, argv: any, done: (completion: ReadonlyArray<string>) => void) => void;
type MiddlewareFunction<T> = (args: Arguments<T>) => void;
type MiddlewareFunction<T = {}> = (args: Arguments<T>) => void;
type Choices = ReadonlyArray<string | true | undefined>;
type PositionalOptionsType = "boolean" | "number" | "string";
}
+78
View File
@@ -307,6 +307,84 @@ function Argv$command() {
.argv;
}
function Argv$commandModule() {
class CommandOne implements yargs.CommandModule {
handler(args: yargs.Arguments): void {
console.log("one");
}
}
const CommandTwo: yargs.CommandModule<{ a: string }, { b: number }> = {
builder: yargs => {
// $ExpectType: string
yargs.argv.a;
return yargs.number("b").default("b", parseInt(yargs.argv.a, 10));
},
handler: argv => {
// $ExpectType: number
argv.b;
}
};
class Configure implements yargs.CommandModule<{ verbose: boolean }, { verbose: boolean, key: string, value: boolean }> {
command = 'configure <key> [value]';
aliases = ['config', 'cfg'];
describe = 'Set a config variable';
builder(yargs: yargs.Argv<{ verbose: boolean }>) {
return yargs.positional('key', { default: '' }).positional('value', { default: true });
}
handler(argv: yargs.Arguments<{ verbose: boolean, key: string, value: string | boolean }>) {
if (argv.verbose) {
console.log(`setting ${argv.key} to ${argv.value}`);
}
}
}
const Configure2: yargs.CommandModule<{ verbose: boolean }, { verbose: boolean, key: string, value: boolean }> = {
command: 'configure <key> [value]',
aliases: ['config', 'cfg'],
describe: 'Set a config variable',
builder: yargs => {
return yargs.positional('key', { default: '' }).positional('value', { default: true });
},
handler: argv => {
if (argv.verbose) {
console.log(`setting ${argv.key} to ${argv.value}`);
}
}
};
const command = 'import-file <file>';
const describe = 'run the importer on a single file';
const builder = (yargs: yargs.Argv) => {
return yargs
.positional('file', {
describe: 'path to file to import'
})
.options({
cleanDestination: {
boolean: true,
describe: 'Clean the destination folder from previously generated files before proceeding.'
}
});
};
const commandArgs = builder(yargs).argv;
// $ExpectType: { [x: string]: unknown; file: unknown; cleanDestination: boolean | undefined; _: string[]; $0: string; }
commandArgs;
// Backwards compatibility with older types
const builder2: yargs.CommandBuilder = builder;
const commandArgs2: yargs.Arguments = builder(yargs).argv;
const commandArgs3: yargs.Arguments = builder2(yargs).argv;
}
function Argv$completion_sync() {
const argv = yargs
.completion('completion', (current, argv) => {