npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@jsxx/bytes

v1.0.1

Published

A lightweight, type-safe utility for converting between bytes and human-readable strings

Readme

@jsxx/bytes

NPM Version License

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/bytes

Quick 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'); // 2147483648

API 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 format
  • options (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" for 0, Infinity, -Infinity, or NaN
  • 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'); // 1125899906842624

Case 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 bytes
  • options (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'); // 2147483648

Types

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')); // 1073741824

File 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'); // false

Custom 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'}); // 104857600

Edge 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'); // NaN

Whitespace 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 error

Function Overloads

TypeScript correctly infers return types:

const str = bytes(1024); // type: string
const num = bytes('1KB'); // type: number

Generic 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 number

Performance

  • 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:

  1. All tests pass: pnpm test
  2. Code follows existing style: pnpm lint
  3. Types are correct: pnpm check-types
  4. Add tests for new features
  5. Update documentation

License

MIT