Package Exports
- @norbulcz/num-parse
Readme
@norbulcz/num-parse
Strict, locale-tolerant number parser (US/EU/CH) with validated grouping. Zero dependencies.
A robust TypeScript library for parsing numbers from strings with support for multiple international formats including US, European, and Swiss number formatting conventions.
Features
- ๐ Multi-locale support: US, EU, and Swiss number formats
- ๐ Strict validation: Validates proper thousands separators and decimal points
- ๐ซ Zero dependencies: Lightweight with no external dependencies
- ๐ฆ TypeScript: Full TypeScript support with type definitions
- ๐งช Well tested: Comprehensive test suite with 300+ test cases
- ๐ฑ Modern: ES modules and CommonJS support
- โก High Performance: 4.4M+ parses per second
Why Choose @norbulcz/num-parse?
- Smaller (1.2KB gzipped, zero deps)
- Stricter (rejects invalid groupings)
- Locale-flexible (US, EU, Swiss, plain, space grouping, with currency symbols)
- Safer (never silently misparses into wrong numbers)
- Simple (no Intl dependency, no polyfills, no moment.js or numeral.js โ just a single function)
- Predictable (invalid input โ returns null, never throws)
Performance
The library is highly optimized for performance:
- 4.4M+ parses per second on modern hardware
- 0.0002ms average parse time per operation
- Pre-compiled regex patterns for maximum efficiency
- Zero dependencies for minimal bundle impact
Bundle Size
- ESM: ~1.2KB gzipped
- CJS: ~1.6KB gzipped
- Types: ~1.4KB
Installation
npm install @norbulcz/num-parseQuickstart
import { parseNumber } from '@norbulcz/num-parse';
// US format
parseNumber("1,234.56"); // โ 1234.56
// European format
parseNumber("1.234,56"); // โ 1234.56
// Swiss format (both apostrophe types)
parseNumber("1'234.56"); // โ 1234.56
parseNumber("1'234.56"); // โ 1234.56 (curly apostrophe)
// Currency symbols (automatically removed)
parseNumber("โช1,234.56"); // โ 1234.56
parseNumber("1,234.56$"); // โ 1234.56
// Plain numbers (no separators)
parseNumber("1234.56"); // โ 1234.56
parseNumber("1234"); // โ 1234
// Space grouping
parseNumber("1 234.56"); // โ 1234.56
parseNumber("1 234 567.89"); // โ 1234567.89Usage
import { parseNumber } from '@norbulcz/num-parse';
// US format
parseNumber('1,234.56'); // โ 1234.56
parseNumber('12,345.67'); // โ 12345.67
// European format
parseNumber('1.234,56'); // โ 1234.56
parseNumber('12.345,67'); // โ 12345.67
// Swiss format (apostrophe as thousands separator)
parseNumber("1'234.56"); // โ 1234.56
parseNumber("1'234,56"); // โ 1234.56
// Negative numbers
parseNumber('-1,234.56'); // โ -1234.56
parseNumber('-1.234,56'); // โ -1234.56
// Edge cases
parseNumber('.5'); // โ 0.5
parseNumber(',5'); // โ 0.5
parseNumber('1,000'); // โ 1000
parseNumber('1.000'); // โ 1000
// Currency symbols (automatically removed)
parseNumber('โช1,234.56'); // โ 1234.56 (Israeli Shekel)
parseNumber('โฟ0.001'); // โ 0.001 (Bitcoin)
parseNumber('โฉ1,234.56'); // โ 1234.56 (Korean Won)
parseNumber('โน1,234.56'); // โ 1234.56 (Indian Rupee)
parseNumber('1,234.56$'); // โ 1234.56 (US Dollar at end)
parseNumber('1.234,56โฌ'); // โ 1234.56 (Euro at end)
// Scientific notation (disabled by default)
parseNumber('1.5e3'); // โ null (disabled by default)
parseNumber('1.5e3', { allowScientific: true }); // โ 1500
// Plain inputs & spaces
parseNumber('3333'); // โ 3333
parseNumber('12345.67'); // โ 12345.67
parseNumber('12345,67'); // โ 12345.67
parseNumber('1 123.34'); // โ 1123.34
parseNumber('2 276,00'); // โ 2276 (NBSP)
// Invalid inputs return null
parseNumber('invalid'); // โ null
parseNumber('1,23,456'); // โ null (invalid grouping)
parseNumber("12'34"); // โ null (invalid apostrophe grouping)
parseNumber('123.'); // โ null (trailing decimal)
parseNumber(''); // โ nullSupported Formats
US Format
- Thousands separator: comma (
,) - Decimal separator: period (
.) - Examples:
1,234.56,12,345.67
European Format
- Thousands separator: period (
.) - Decimal separator: comma (
,) - Examples:
1.234,56,12.345,67
Swiss Format
- Thousands separator: apostrophe (
') - Decimal separator: period (
.) or comma (,) - Examples:
1'234.56,1'234,56
Currency Symbol Support
- Automatically removes all Unicode currency symbols using the
\p{Sc}class - Supports:
$,โฌ,ยฃ,ยฅ,โน,โฝ,ยข,โช,โฟ,โฉ,โซ,โด,โฆ,โต, and many more - Examples:
โช1,234.56โ1234.56,โฟ0.001โ0.001
API
parseNumber(value: string, options?: ParseOptions): number | null
Parses a string and returns a number or null if the input is invalid.
Parameters:
value(string): The string to parseoptions(ParseOptions, optional): Configuration options
Returns:
number: The parsed numbernull: If the input is invalid or empty
ParseOptions
interface ParseOptions {
/** Strip any Unicode currency symbol (e.g. $, โฌ, โช, โฟ). Default: true */
stripCurrency?: boolean;
/** Allow Swiss-style apostrophe grouping (both ' and '). Default: true */
allowApostrophe?: boolean;
/** Allow scientific notation like 1.5e3. Default: false */
allowScientific?: boolean;
}Options Examples
// Default behavior
parseNumber(input, {
stripCurrency: true, // \p{Sc} removed by default
allowApostrophe: true, // Swiss ' and ' grouping
allowScientific: false // opt-in
});
// Disable currency stripping
parseNumber('$1,234.56', { stripCurrency: false }); // โ null
parseNumber('1,234.56', { stripCurrency: false }); // โ 1234.56
// Disable Swiss apostrophe format
parseNumber("1'234.56", { allowApostrophe: false }); // โ null
parseNumber('1,234.56', { allowApostrophe: false }); // โ 1234.56
// Enable scientific notation
parseNumber('1.5e3', { allowScientific: true }); // โ 1500
parseNumber('1.5e-3', { allowScientific: true }); // โ 0.0015
// Combine options
parseNumber('โช1'234.56', {
stripCurrency: true,
allowApostrophe: true,
allowScientific: false
}); // โ 1234.56Validation Rules
The parser enforces strict validation rules:
- Thousands separators must be in groups of exactly 3 digits
- Decimal points can only appear once
- Signs (
+/-) can only appear at the beginning - Swiss apostrophes must follow proper 3-digit grouping
- Mixed separators are disambiguated by the last separator (decimal point)
Examples
// Valid inputs
parseNumber('1,234.56'); // โ
1234.56
parseNumber('1.234,56'); // โ
1234.56
parseNumber("1'234.56"); // โ
1234.56
parseNumber('1,000'); // โ
1000
parseNumber('1.000'); // โ
1000
parseNumber("1'000"); // โ
1000
parseNumber('-1,234.56'); // โ
-1234.56
parseNumber('.5'); // โ
0.5
parseNumber(',5'); // โ
0.5
// Invalid inputs
parseNumber('1,23,456'); // โ null (invalid grouping)
parseNumber('1.23.456'); // โ null (invalid grouping)
parseNumber('1,234.56.78'); // โ null (multiple decimal points)
parseNumber('1-234.56'); // โ null (sign in middle)
parseNumber('1,234,56'); // โ null (ambiguous - could be 1,234,56 or 1,234.56)
parseNumber(''); // โ null (empty)
parseNumber('invalid'); // โ null (non-numeric)Performance Benchmarks
Real-world Performance
Running performance benchmark...
Total time: 1170.28ms
Average time per parse: 0.0002ms
Parses per second: 4,443,387
Total operations: 5,200,000Test Cases Covered
- US format:
1,234.56 - EU format:
1.234,56 - Swiss format:
1'234.56 - Scientific notation:
1.5e3 - Currency symbols:
โช1,234.56,1,234.56$ - Large numbers:
999,999,999.99 - Small decimals:
0.001
Optimization Features
- Pre-compiled regex patterns - No regex compilation overhead
- Method extraction - Clean, maintainable code structure
- Early returns - Minimal processing for invalid inputs
- Unicode optimization - Efficient
\p{Sc}class usage
Development
# Install dependencies
npm install
# Run tests
npm test
# Run tests in watch mode
npm run test:watch
# Build the library
npm run build
# Development mode with watch
npm run devContributing
Contributions are welcome! Please open issues or pull requests on GitHub.
License
MIT ยฉ Norbert Lorincz