Skip to content

Commit 86c85bd

Browse files
authored
Merge pull request #32 from jakeboone02:bigint
Add `bigint` support
2 parents 936cbe6 + 6be6eaa commit 86c85bd

File tree

9 files changed

+64
-8
lines changed

9 files changed

+64
-8
lines changed

CHANGELOG.md

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,12 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
99

1010
- N/A
1111

12+
## [v2.1.0] - 2025-06-09
13+
14+
### Added
15+
16+
- `bigIntOnOverflow` option will produce a `bigint` value if the input represents a valid integer greater than `Number.MAX_SAFE_INTEGER` or less than `Number.MIN_SAFE_INTEGER`.
17+
1218
## [v2.0.1] - 2024-01-15
1319

1420
### Fixed
@@ -169,7 +175,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
169175

170176
<!-- Release comparison links -->
171177

172-
[unreleased]: https://github.com/jakeboone02/numeric-quantity/compare/v2.0.0...HEAD
178+
[unreleased]: https://github.com/jakeboone02/numeric-quantity/compare/v2.1.0...HEAD
179+
[v2.1.0]: https://github.com/jakeboone02/numeric-quantity/compare/v2.0.1...v2.1.0
180+
[v2.0.1]: https://github.com/jakeboone02/numeric-quantity/compare/v2.0.0...v2.0.1
173181
[v2.0.0]: https://github.com/jakeboone02/numeric-quantity/compare/v1.0.4...v2.0.0
174182
[v1.0.4]: https://github.com/jakeboone02/numeric-quantity/compare/v1.0.3...v1.0.4
175183
[v1.0.3]: https://github.com/jakeboone02/numeric-quantity/compare/v1.0.2...v1.0.3

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ Features:
1313
- In addition to plain integers and decimals, `numeric-quantity` can parse numbers with comma or underscore separators (`'1,000'` or `'1_000'`), mixed numbers (`'1 2/3'`), vulgar fractions (`'1⅖'`), and the fraction slash character (`'1 2⁄3'`).
1414
- To allow and ignore trailing invalid characters _à la_ `parseFloat`, pass `{ allowTrailingInvalid: true }` as the second argument.
1515
- To parse Roman numerals like `'MCCXIV'` or `'Ⅻ'`, pass `{ romanNumerals: true }` as the second argument or call `parseRomanNumerals` directly.
16+
- To produce `bigint` values when the input represents an integer that would exceeds the boundaries of `number`, pass `{ bigIntOnOverflow: true }` as the second argument.
1617
- Results will be rounded to three decimal places by default. To avoid rounding, pass `{ round: false }` as the second argument. To round to a different number of decimal places, assign that number to the `round` option (`{ round: 5 }` will round to five decimal places).
1718
- Returns `NaN` if the provided string does not resemble a number.
1819

src/constants.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,4 +235,5 @@ export const defaultOptions: Required<NumericQuantityOptions> = {
235235
round: 3,
236236
allowTrailingInvalid: false,
237237
romanNumerals: false,
238+
bigIntOnOverflow: false,
238239
} as const;

src/dev.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,12 @@ for (const [title, tests] of Object.entries(numericQuantityTests)) {
2222

2323
for (const [test, expect, opts] of tests) {
2424
const result = numericQuantity(test, opts);
25-
const pass = isNaN(expect) ? isNaN(result) : expect === result;
25+
const pass =
26+
typeof expect === 'bigint'
27+
? expect === (result as unknown as bigint)
28+
: isNaN(expect)
29+
? isNaN(result)
30+
: expect === result;
2631
const testTR = document.createElement('tr');
2732
const tdCall = document.createElement('td');
2833
const tdResult = document.createElement('td');

src/index.test.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { describe, expect, test } from 'bun:test';
1+
import { describe, expect, Matchers, test } from 'bun:test';
22
import { numericQuantity } from './numericQuantity';
33
import { numericQuantityTests } from './numericQuantityTests';
44

@@ -15,7 +15,9 @@ for (const [title, tests] of Object.entries(numericQuantityTests)) {
1515
: ''
1616
} should evaluate to ${expected}`, () => {
1717
const expectation = expect(numericQuantity(arg, options));
18-
if (isNaN(expected)) {
18+
if (typeof expected === 'bigint') {
19+
(expectation as unknown as Matchers<bigint>).toBe(expected);
20+
} else if (isNaN(expected)) {
1921
expectation.toBeNaN();
2022
} else {
2123
expectation.toBe(expected);

src/numericQuantity.ts

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,20 @@ const spaceThenSlashRegex = /^\s*\//;
1515
*
1616
* The string can include mixed numbers, vulgar fractions, or Roman numerals.
1717
*/
18-
export const numericQuantity = (
18+
function numericQuantity(quantity: string | number): number;
19+
function numericQuantity(quantity: string | number): number;
20+
function numericQuantity(
21+
quantity: string | number,
22+
options: NumericQuantityOptions & { bigIntOnOverflow: true }
23+
): number | bigint;
24+
function numericQuantity(
25+
quantity: string | number,
26+
options?: NumericQuantityOptions
27+
): number;
28+
function numericQuantity(
1929
quantity: string | number,
2030
options: NumericQuantityOptions = defaultOptions
21-
): number => {
31+
) {
2232
if (typeof quantity === 'number' || typeof quantity === 'bigint') {
2333
return quantity;
2434
}
@@ -65,6 +75,16 @@ export const numericQuantity = (
6575
if (!numberGroup1 && numberGroup2 && numberGroup2.startsWith('.')) {
6676
finalResult = 0;
6777
} else {
78+
if (opts.bigIntOnOverflow) {
79+
const asBigInt = dash ? BigInt(`-${numberGroup1}`) : BigInt(numberGroup1);
80+
if (
81+
asBigInt > BigInt(Number.MAX_SAFE_INTEGER) ||
82+
asBigInt < BigInt(Number.MIN_SAFE_INTEGER)
83+
) {
84+
return asBigInt;
85+
}
86+
}
87+
6888
finalResult = parseInt(numberGroup1);
6989
}
7090

@@ -106,4 +126,6 @@ export const numericQuantity = (
106126
}
107127

108128
return dash ? finalResult * -1 : finalResult;
109-
};
129+
}
130+
131+
export { numericQuantity };

src/numericQuantityTests.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,11 @@ export const numericQuantityTests: Record<
1414
(
1515
| [string | number, number]
1616
| [string | number, number, NumericQuantityOptions]
17+
| [
18+
string | number,
19+
number | bigint,
20+
NumericQuantityOptions & { bigIntOnOverflow: true },
21+
]
1722
)[]
1823
> = {
1924
'Non-numeric stuff': [
@@ -216,6 +221,12 @@ export const numericQuantityTests: Record<
216221
['1⁄2', 0.5],
217222
['2 1⁄2', 2.5],
218223
],
224+
BigInts: [
225+
['9007199254740992', 9007199254740992n, { bigIntOnOverflow: true }],
226+
['-9007199254740992', -9007199254740992n, { bigIntOnOverflow: true }],
227+
['123', 123, { bigIntOnOverflow: true }],
228+
['-123', -123, { bigIntOnOverflow: true }],
229+
],
219230
'Roman numerals': (
220231
[
221232
// Invalid

src/types.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,11 @@ export interface NumericQuantityOptions {
1818
* @default false
1919
*/
2020
romanNumerals?: boolean;
21+
/**
22+
* Generates a `bigint` value if the string represents
23+
* a valid integer too large for the `number` type.
24+
*/
25+
bigIntOnOverflow?: boolean;
2126
}
2227

2328
/**

tsconfig.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@
1111
"esModuleInterop": true,
1212
"noEmit": true,
1313
"skipLibCheck": true,
14-
"lib": ["ES2015", "DOM"]
14+
"lib": ["ES2015", "DOM"],
15+
"target": "es2020"
1516
},
1617
"include": ["./*.ts", "./src"]
1718
}

0 commit comments

Comments
 (0)