From 41762dbd3800cfb154dbfbfb85e505a000ace190 Mon Sep 17 00:00:00 2001 From: Jaksenc Date: Thu, 14 May 2026 13:18:09 -0400 Subject: [PATCH] Parse negative values for numeric parser types --- index.js | 24 ++++++++++++++++-------- test.js | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+), 8 deletions(-) diff --git a/index.js b/index.js index 3f60f4c..dbd79bb 100644 --- a/index.js +++ b/index.js @@ -10,6 +10,16 @@ class ArgError extends Error { } } +function isNumericType(type) { + return ( + type === Number || + type === parseInt || + type === parseFloat || + // eslint-disable-next-line no-undef + (typeof BigInt !== 'undefined' && type === BigInt) + ); +} + function arg( opts, { @@ -59,6 +69,7 @@ function arg( let type = opts[key]; let isFlag = false; + let isNumeric = false; if ( Array.isArray(type) && @@ -66,12 +77,14 @@ function arg( typeof type[0] === 'function' ) { const [fn] = type; + isNumeric = isNumericType(fn); type = (value, name, prev = []) => { prev.push(fn(value, name, prev[prev.length - 1])); return prev; }; isFlag = fn === Boolean || fn[flagSymbol] === true; } else if (typeof type === 'function') { + isNumeric = isNumericType(type); isFlag = type === Boolean || type[flagSymbol] === true; } else { throw new ArgError( @@ -87,7 +100,7 @@ function arg( ); } - handlers[key] = [type, isFlag]; + handlers[key] = [type, isFlag, isNumeric]; } for (let i = 0, len = argv.length; i < len; i++) { @@ -136,7 +149,7 @@ function arg( } } - const [type, isFlag] = handlers[argName]; + const [type, isFlag, isNumeric] = handlers[argName]; if (!isFlag && j + 1 < separatedArguments.length) { throw new ArgError( @@ -152,12 +165,7 @@ function arg( argv.length < i + 2 || (argv[i + 1].length > 1 && argv[i + 1][0] === '-' && - !( - argv[i + 1].match(/^-?\d*(\.(?=\d))?\d*$/) && - (type === Number || - // eslint-disable-next-line no-undef - (typeof BigInt !== 'undefined' && type === BigInt)) - )) + !(argv[i + 1].match(/^-?\d*(\.(?=\d))?\d*$/) && isNumeric)) ) { const extended = originalArgName === argName ? '' : ` (alias for ${argName})`; diff --git a/test.js b/test.js index 49e638f..a8f1901 100644 --- a/test.js +++ b/test.js @@ -522,6 +522,62 @@ test('should parse negative numbers (separate argument form)', () => { }); }); +test('should parse negative numbers with parseInt', () => { + const argv = ['--int', '-100']; + + const result = arg( + { + '--int': parseInt + }, + { + argv + } + ); + + expect(result).to.deep.equal({ + _: [], + '--int': -100 + }); +}); + +test('should parse negative numbers with parseFloat', () => { + const argv = ['--float', '-0.1']; + + const result = arg( + { + '--float': parseFloat + }, + { + argv + } + ); + + expect(result).to.deep.equal({ + _: [], + '--float': -0.1 + }); +}); + +test('should parse negative numbers for numeric array types', () => { + const argv = ['--int', '-5', '--custom-int', '-10']; + + const result = arg( + { + '--int': [Number], + '--custom-int': [parseInt] + }, + { + argv + } + ); + + expect(result).to.deep.equal({ + _: [], + '--int': [-5], + '--custom-int': [-10] + }); +}); + test('should error if numeric type is followed by non-negative, non-argument', () => { const argv = ['--int', '-abc'];