@jsxx/bytes
v1.0.1
Published
A lightweight, type-safe utility for converting between bytes and human-readable strings
Maintainers
Readme
@jsxx/bytes
A lightweight, type-safe utility library for converting between bytes and human-readable strings.
Features
- Zero dependencies - Minimal footprint
- Type-safe - Full TypeScript support with template literal types
- Dual API - Single function for both formatting and parsing
- Smart formatting - Auto-hides unnecessary decimals
- Customizable - Control precision and formatting
- Fast - Optimized for performance
- Well-tested - Comprehensive test coverage
Installation
npm add @jsxx/bytes
# or
pnpm add @jsxx/bytes
# or
yarn add @jsxx/bytes
# or
bun add @jsxx/bytesQuick Start
import bytes from '@jsxx/bytes';
// Format bytes to human-readable string
bytes(1024); // "1KB"
bytes(1536); // "1.5KB"
bytes(1048576); // "1MB"
// Parse human-readable string to bytes
bytes('1KB'); // 1024
bytes('1.5MB'); // 1572864
bytes('2GB'); // 2147483648API Reference
bytes(value, options?)
Main function with overloaded signatures for bidirectional conversion.
Signature 1: Format bytes to string
function bytes(value: number, options?: FormatOptions): string;Converts a numeric byte count into a human-readable string using binary units (1024-based).
Parameters:
value(number): The number of bytes to formatoptions(FormatOptions): Optional formatting options
Returns: string - Formatted string like "1.5KB" or "2MB"
Examples:
bytes(0); // "0B"
bytes(500); // "500B"
bytes(1024); // "1KB"
bytes(1536); // "1.5KB"
bytes(1048576); // "1MB"
bytes(1073741824); // "1GB"
bytes(-1024); // "-1KB"
// With custom decimals
bytes(1536, {decimals: 0}); // "2KB"
bytes(1536, {decimals: 2}); // "1.5KB"
bytes(1075, {decimals: 2}); // "1.05KB"
// With separator
bytes(1024, {separator: ' '}); // "1 KB"
bytes(1536, {separator: ' '}); // "1.5 KB"
// Combined options
bytes(1536, {decimals: 2, separator: ' '}); // "1.5 KB"Edge Cases:
- Returns
"0B"for0,Infinity,-Infinity, orNaN - Supports negative numbers:
-1024→"-1KB" - Automatically hides unnecessary decimals:
1024→"1KB"(not "1.0KB") - Maximum supported unit:
PB(Petabyte)
Signature 2: Parse string to bytes
function bytes(value: ByteString | string): number;Parses a human-readable byte string into a numeric byte count using binary units (1024-based).
Parameters:
value(ByteString | string): A formatted byte string (e.g.,"10MB","512KB")
Returns: number - The number of bytes
Examples:
bytes('1B'); // 1
bytes('1KB'); // 1024
bytes('1.5KB'); // 1536
bytes('1MB'); // 1048576
bytes('1GB'); // 1073741824
bytes('1TB'); // 1099511627776
bytes('1PB'); // 1125899906842624Case Handling:
bytes('1kb'); // 1024 (lowercase works)
bytes('1KB'); // 1024 (uppercase works)
bytes('1Kb'); // 1024 (mixed case works)Throws:
- Invalid format (e.g.,
"ABC","100"without unit,"KB"without number)
Returns NaN:
- Invalid decimal format:
"1.2.3KB","..5MB"(matches regex but invalid number)
formatBytes(bytes, options?)
Explicit function to format bytes to a human-readable string.
function formatBytes(bytes: number, options?: FormatOptions): string;Parameters:
bytes(number): The number of bytesoptions(FormatOptions): Optional formatting options
Returns: string
Example:
import {formatBytes} from '@jsxx/bytes';
formatBytes(1024); // "1KB"
formatBytes(1536); // "1.5KB"
formatBytes(1048576); // "1MB"
formatBytes(1536, {decimals: 0}); // "2KB"
formatBytes(1024, {separator: ' '}); // "1 KB"parseBytes(value)
Explicit function to parse a byte string into a number.
function parseBytes(value: ByteString | string): number;Parameters:
value(ByteString | string): A formatted byte string
Returns: number
Throws: Error if the string format is invalid
Example:
import {parseBytes} from '@jsxx/bytes';
parseBytes('1KB'); // 1024
parseBytes('1.5MB'); // 1572864
parseBytes('2GB'); // 2147483648Types
ByteUnit
type ByteUnit = 'B' | 'KB' | 'MB' | 'GB' | 'TB' | 'PB';Supported byte units (binary, 1024-based).
ByteString
type ByteString = `${number}${ByteUnit}` | `${number}${Lowercase<ByteUnit>}`;Template literal type for type-safe byte strings. Ensures compile-time checking for valid formats.
Valid formats:
"1KB","1.5MB","2GB"(uppercase units)"1kb","1.5mb","2gb"(lowercase units)
Invalid formats (caught at compile-time):
"1 KB"(space not allowed in type, but works at runtime)"KB"(number required)"100"(unit required)
FormatOptions
interface FormatOptions {
/**
* Number of decimal places to display.
* @default 1
*/
decimals?: number;
/**
* Separator between number and unit.
* @default ''
*/
separator?: string;
}Options for customizing byte formatting.
Supported Units
All units use binary (base-1024) calculation:
| Unit | Name | Bytes | Calculation | | ---- | -------- | --------------------- | ----------- | | B | Byte | 1 | 1 | | KB | Kilobyte | 1,024 | 1024¹ | | MB | Megabyte | 1,048,576 | 1024² | | GB | Gigabyte | 1,073,741,824 | 1024³ | | TB | Terabyte | 1,099,511,627,776 | 1024⁴ | | PB | Petabyte | 1,125,899,906,842,624 | 1024⁵ |
Usage Examples
Basic Formatting
import bytes from '@jsxx/bytes';
console.log(bytes(1024)); // "1KB"
console.log(bytes(1536)); // "1.5KB"
console.log(bytes(1048576)); // "1MB"
console.log(bytes(5242880)); // "5MB"
console.log(bytes(1073741824)); // "1GB"Basic Parsing
import bytes from '@jsxx/bytes';
console.log(bytes('1KB')); // 1024
console.log(bytes('1.5KB')); // 1536
console.log(bytes('5MB')); // 5242880
console.log(bytes('1GB')); // 1073741824File Size Display
import bytes from '@jsxx/bytes';
function displayFileSize(fileSizeInBytes: number) {
return `File size: ${bytes(fileSizeInBytes)}`;
}
displayFileSize(2048); // "File size: 2KB"
displayFileSize(5242880); // "File size: 5MB"Parsing User Input
import bytes from '@jsxx/bytes';
function validateUploadSize(input: string, maxSize: string) {
const uploadBytes = bytes(input as ByteString);
const maxBytes = bytes(maxSize as ByteString);
return uploadBytes <= maxBytes;
}
validateUploadSize('5MB', '10MB'); // true
validateUploadSize('15MB', '10MB'); // falseCustom Precision
import bytes from '@jsxx/bytes';
// Default: 1 decimal place (auto-hidden if zero)
bytes(1024); // "1KB"
bytes(1536); // "1.5KB"
// No decimals (rounded)
bytes(1536, {decimals: 0}); // "2KB"
bytes(1700, {decimals: 0}); // "2KB"
// 2 decimal places
bytes(1075, {decimals: 2}); // "1.05KB"
bytes(1100, {decimals: 2}); // "1.07KB"
// 3 decimal places
bytes(1075, {decimals: 3}); // "1.05KB"
bytes(1100, {decimals: 3}); // "1.074KB"With Separators
import bytes from '@jsxx/bytes';
// Space separator
bytes(1024, {separator: ' '}); // "1 KB"
bytes(1536, {separator: ' '}); // "1.5 KB"
// Custom separators
bytes(1024, {separator: '-'}); // "1-KB"
bytes(1536, {separator: '_'}); // "1.5_KB"
// Combined with decimals
bytes(1536, {decimals: 2, separator: ' '}); // "1.5 KB"
bytes(1024, {decimals: 0, separator: ' '}); // "1 KB"Memory Usage Monitoring
import bytes from '@jsxx/bytes';
const memoryUsage = process.memoryUsage();
console.log('RSS:', bytes(memoryUsage.rss));
console.log('Heap Total:', bytes(memoryUsage.heapTotal));
console.log('Heap Used:', bytes(memoryUsage.heapUsed));Network Transfer Display
import bytes from '@jsxx/bytes';
function showDownloadProgress(downloaded: number, total: number) {
return `${bytes(downloaded)} / ${bytes(total)}`;
}
showDownloadProgress(524288, 1048576); // "512KB / 1MB"Configuration Parsing
import bytes from '@jsxx/bytes';
interface CacheConfig {
maxSize: string;
}
function getCacheMaxBytes(config: CacheConfig): number {
return bytes(config.maxSize as ByteString);
}
getCacheMaxBytes({maxSize: '100MB'}); // 104857600Edge Cases & Behavior
Zero and Special Values
bytes(0); // "0B"
bytes(Infinity); // "0B"
bytes(-Infinity); // "0B"
bytes(NaN); // "0B"Negative Numbers
bytes(-1024); // "-1KB"
bytes(-1048576); // "-1MB"Smart Decimal Hiding
The library automatically hides unnecessary decimal places:
bytes(1024); // "1KB" (not "1.0KB")
bytes(2048); // "2KB" (not "2.0KB")
bytes(1536); // "1.5KB" (keeps non-zero decimal)
bytes(1075); // "1.05KB" (keeps necessary decimals)You can control this with the decimals option:
bytes(1024, {decimals: 2}); // "1KB" (still hides if zero)
bytes(1075, {decimals: 2}); // "1.05KB"
bytes(1100, {decimals: 3}); // "1.074KB"Precision
Parsing uses Math.floor() for decimal results:
bytes('1.5KB'); // 1536 (exactly 1.5 * 1024)
bytes('1.999KB'); // 2046 (floor of 1.999 * 1024)
bytes('0.5MB'); // 524288 (floor of 0.5 * 1048576)Invalid Input
// Throws error
parseBytes('invalid'); // Error: Invalid byte string: invalid
parseBytes(''); // Error: Invalid byte string:
parseBytes('100'); // Error: Invalid byte string: 100
parseBytes('KB'); // Error: Invalid byte string: KB
// Returns NaN (matches regex but invalid number)
parseBytes('1.2.3KB'); // NaN
parseBytes('..5MB'); // NaNWhitespace Handling
Runtime whitespace is trimmed (though TypeScript type doesn't allow it):
parseBytes(' 1KB ' as ByteString); // 1024 (works at runtime)TypeScript Usage
Type Safety
import bytes, {ByteString} from '@jsxx/bytes';
// Valid at compile-time
const size: ByteString = '1.5MB';
bytes(size); // ✓
// Invalid at compile-time
const invalid: ByteString = '1 MB'; // ✗ Type error (but works at runtime)
const invalid2: ByteString = '100'; // ✗ Type errorFunction Overloads
TypeScript correctly infers return types:
const str = bytes(1024); // type: string
const num = bytes('1KB'); // type: numberGeneric Usage
function formatSize<T extends number | ByteString>(
value: T,
): T extends number ? string : number {
return bytes(value as any);
}
formatSize(1024); // Returns string
formatSize('1KB'); // Returns numberPerformance
- Lightweight: ~1KB minified + gzipped
- Fast: O(1) time complexity for both formatting and parsing
- Efficient: Pre-computed unit mappings, minimal allocations
- No regex overhead: Only one regex match per parse operation
Browser Support
Works in all modern browsers and Node.js environments that support:
- ES2015+ features
Number.isFinite()Math.log(),Math.floor(),Math.pow()String.prototype.trim(),String.prototype.match()
Why @jsxx/bytes?
vs bytes (popular npm package)
| Feature | @jsxx/bytes | bytes | | ---------------------- | ----------- | ------- | | Bundle size | ~1KB | ~2.5KB | | TypeScript types | ✓ Built-in | ✓ | | Template literal types | ✓ | ✗ | | Auto-hide decimals | ✓ | ✗ | | Custom decimals | ✓ | ✓ | | Custom separator | ✓ | ✗ | | Tree-shakeable | ✓ | Limited | | ESM-first | ✓ | ✗ |
Key Advantages
- Smaller bundle size - 60% smaller than popular alternatives
- Better TypeScript support - Template literal types for compile-time safety
- Smarter formatting - Auto-hides unnecessary decimals
- Modern - Written with modern JavaScript, ESM-first
- Well-tested - Comprehensive test coverage including edge cases
- Part of @jsxx ecosystem - Consistent API across @jsxx packages
Contributing
Contributions are welcome! Please ensure:
- All tests pass:
pnpm test - Code follows existing style:
pnpm lint - Types are correct:
pnpm check-types - Add tests for new features
- Update documentation
License
MIT
