6

I have the following code on my app:

import commander = require('commander');

commander
  .option('-u, --user [user]', 'user code')
  .option('-p, --pass [pass]', 'pass code')
  .parse(process.argv);

Then I try to access:

commander.user

But I get an error (commander.d.ts from DefinitelyTyped):

user does not exist on type IExportedCommand

I tried adding this

interface IExportedCommand {
  user: string;
  pass: string;
}

But I still get the error. How can I fix this?

BrunoLM
  • 97,872
  • 84
  • 296
  • 452

4 Answers4

10

You can also do:

npm install --save-dev @types/commander

EDIT: Commander now includes its own TypeScript typings, so this should no longer be necessary.

gpresland
  • 1,690
  • 2
  • 20
  • 31
  • I feel this is a better answer as it leveraged existing typings built by the open source community. I assume the end goal of the user is to "use the typing from typescript", not just to prevent compiler errors. – Chuanqi Sun Jul 30 '18 at 03:29
  • 1
    Just as a note Commander now ships with its own types, no need anymore to install `@types/commander` – marko424 May 03 '22 at 12:17
5

Create a file commander-expansion.d.ts with the following :

declare namespace commander {
    interface IExportedCommand extends ICommand {
        user: string; 
        pass: string;
    }
}

Tip

Because I did something like this recently, recommend --auth user:password. Saves you dealing with user missing username or password. But prevents using : as a password property

¯\_(ツ)_/¯

More : https://github.com/alm-tools/alm/blob/master/src/server/commandLine.ts#L24

basarat
  • 261,912
  • 58
  • 460
  • 511
1

You can keep the Typescript interface within the same file.

interface InterfaceCLI extends commander.ICommand {
  user?: string
  password?: string
}

After you can define this interface to a variable after running the program.parse function.

const cli: InterfaceCLI = program.parse(process.argv)
console.log(cli.user, cli.password)

I hope this helps!

user1116928
  • 149
  • 2
0

I know this topic is old but I had a lot of trouble finding help with it. I solved it, but I am not yet fluent in either Typescript or JavaScript, and would like some feedback.

After reading the answers above I could not figure out where the type ICommand was located. However I did find a type name Command.

Furthermore the various snippets use inconsistent variable names which made them difficult to decipher.

So I played around a while and came up with this complete example. The entire app is in one file:

import commander = require('commander');

interface InterfaceCLI extends commander.Command {
    user?: string
    password?: string
}
class Startup {
    public static main(): number {
        const cli: InterfaceCLI = commander
            .option('-u, --user [user]', 'user id')
            .option('-p, --password [password]', 'user\'s password')
            .parse(process.argv);
        console.log(cli.user, cli.password);

        return 0;
    }
}

Startup.main();

Dependencies: install commander@2.16.0 --save

Please let me know what you think of this solution as I intend to use it as the starting point of a production command line application.

BigTFromAZ
  • 684
  • 7
  • 22