yargs: "Automagic" conversion of number-like strings is unexpected and frustrating

I’m building a CLI with lots of options, spread across lots of nested commands. I recently noticed (by pure luck) that an option that was accepts a phone number was being “automagically” converted to a number and losing the leading zero. After some digging, the cause is this feature:

Numbers

Every argument that looks like a number (!isNaN(Number(arg))) is converted to one. This way you can just net.createConnection(argv.port) and you can add numbers out of argv with + without having that mean concatenation, which is super frustrating.

I think this feature is more detrimental than helpful. Now I have to worry about any option input that looks numeric getting coerced when it shouldn’t be.

In order to mitigate the issue entirely for my use-case, I’d need to apply my own coercion function to every option in my entire interface! Wouldn’t a better solution be to provide some built-in coercion functions that can be applied to options that desire this behavior on a case-by-case basis?

Another solution to this problem might be to provide an option to turn automatic coercion on or off. Even then, this behavior should probably be opt-in rather than opt-out, to avoid violating the principle of least astonishment.

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Reactions: 9
  • Comments: 16 (7 by maintainers)

Most upvoted comments

Hey,

actually there is really simple way to deal with it. Having script like this:

const args = yargs
    .option('number-option', {
        description: 'b',
        number: true
    })
    .option('string-option', {
        string: true
    })
    .argv;

console.log(args);

look at the option called string-option. By assigning it string: true property you are stopping yargs from parsing it like a number.

Output from

$ node index.js --string-option=15 --number-option=12

is

{ _: [],
  help: false,
  version: false,
  'string-option': '15',
  stringOption: '15',
  'number-option': 12,
  numberOption: 12,
  '$0': 'index.js' }

so as you can see 15 is string, while 12 was parsed as a number.

Similiar issue: https://github.com/yargs/yargs/issues/938

Note that you can also disable the feature entirely via yargs config in your package.json. See the parse-numbers option here: https://github.com/yargs/yargs/blob/master/docs/advanced.md#customizing

@ogonkov @ezzatron @Morishiri there are now a few upstream fixes in yargs-parser which address this issue:

https://github.com/yargs/yargs-parser/pull/110

We don’t attempt automatic conversion to numbers if the conversion would result in losing information. I will have a new version of yargs out the door today.

@gregorskii @ezzatron see https://github.com/yargs/yargs-parser/pull/104, which I think is a step in the right direction.