or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

date-time-formatting.mddisplay-name-formatting.mdindex.mdintl-instance.mdlist-formatting.mdmessage-formatting.mdnumber-formatting.mdrelative-time-pluralization.mdutility-functions.md
tile.json

number-formatting.mddocs/

Number Formatting

Number formatting with support for currencies, units, compact notation, and custom number systems. Provides both individual functions and intl instance methods for locale-aware number presentation with extensive customization options.

Capabilities

formatNumber Function

Formats numbers according to locale with support for various styles and options.

/**
 * Format numbers according to locale and style options
 * @param config - Configuration with locale, formats, and error handler
 * @param getNumberFormat - Number formatter factory function
 * @param value - Number or bigint value to format
 * @param options - Formatting options including style, currency, and precision
 * @returns Formatted number string
 */
function formatNumber(
  config: {
    locale: string;
    formats: CustomFormats;
    onError: OnErrorFn;
  },
  getNumberFormat: Formatters['getNumberFormat'],
  value: number | bigint,
  options?: FormatNumberOptions
): string;

formatNumberToParts Function

Formats numbers returning arrays of parts for custom rendering and styling.

/**
 * Format numbers returning array of parts for custom rendering
 * @param config - Configuration with locale, formats, and error handler
 * @param getNumberFormat - Number formatter factory function  
 * @param value - Number or bigint value to format
 * @param options - Formatting options
 * @returns Array of number parts with types and values
 */
function formatNumberToParts(
  config: {
    locale: string;
    formats: CustomFormats;
    onError: OnErrorFn;
  },
  getNumberFormat: Formatters['getNumberFormat'],
  value: number | bigint,
  options?: FormatNumberOptions
): Intl.NumberFormatPart[];

Usage Examples:

import { formatNumber, formatNumberToParts, createFormatters } from "@formatjs/intl";

const config = {
  locale: 'en-US',
  formats: {
    number: {
      currency: { style: 'currency', currency: 'USD' },
      percentage: { style: 'percent', minimumFractionDigits: 1 },
      compact: { notation: 'compact', compactDisplay: 'short' }
    }
  },
  onError: console.error
};

const formatters = createFormatters();

// Basic number formatting
const basic = formatNumber(config, formatters.getNumberFormat, 1234.56);
// Result: "1,234.56"

// Currency formatting
const currency = formatNumber(config, formatters.getNumberFormat, 1234.56, {
  style: 'currency',
  currency: 'USD'
});
// Result: "$1,234.56"

// Percentage formatting
const percentage = formatNumber(config, formatters.getNumberFormat, 0.1234, {
  style: 'percent',
  minimumFractionDigits: 1
});
// Result: "12.3%"

// Compact notation
const compact = formatNumber(config, formatters.getNumberFormat, 1234567, {
  notation: 'compact',
  compactDisplay: 'short'
});
// Result: "1.2M"

// Using custom formats
const customCurrency = formatNumber(config, formatters.getNumberFormat, 99.99, {
  format: 'currency'
});
// Result: "$99.99"

FormatNumberOptions Interface

Comprehensive options for number formatting with all Intl.NumberFormat capabilities.

type FormatNumberOptions = Omit<NumberFormatOptions, 'localeMatcher'> & {
  /** Named format reference from custom formats */
  format?: string;
};

interface NumberFormatOptions {
  /** Number formatting style */
  style?: 'decimal' | 'currency' | 'percent' | 'unit';
  /** Currency code for currency style */
  currency?: string;
  /** Unit identifier for unit style */  
  unit?: string;
  /** Unit display format */
  unitDisplay?: 'short' | 'narrow' | 'long';
  /** Whether to use grouping separators */
  useGrouping?: boolean | 'always' | 'auto' | 'min2';
  
  /** Minimum number of integer digits */
  minimumIntegerDigits?: number;
  /** Minimum number of fraction digits */
  minimumFractionDigits?: number;
  /** Maximum number of fraction digits */
  maximumFractionDigits?: number;
  /** Minimum number of significant digits */
  minimumSignificantDigits?: number;
  /** Maximum number of significant digits */
  maximumSignificantDigits?: number;
  
  /** Compact display mode */
  compactDisplay?: 'short' | 'long';
  /** Currency display format */
  currencyDisplay?: 'symbol' | 'narrowSymbol' | 'code' | 'name';
  /** Currency sign display */
  currencySign?: 'standard' | 'accounting';
  /** Number notation style */
  notation?: 'standard' | 'scientific' | 'engineering' | 'compact';
  /** Sign display mode */
  signDisplay?: 'auto' | 'never' | 'always' | 'exceptZero';
  /** Numbering system */
  numberingSystem?: string;
  
  /** Trailing zero display (ES2023) */
  trailingZeroDisplay?: 'auto' | 'stripIfInteger';
  /** Rounding priority (ES2023) */
  roundingPriority?: 'auto' | 'morePrecision' | 'lessPrecision';
  /** Rounding increment (ES2023) */
  roundingIncrement?: 1 | 2 | 5 | 10 | 20 | 25 | 50 | 100 | 200 | 250 | 500 | 1000 | 2000 | 2500 | 5000;
  /** Rounding mode (ES2023) */
  roundingMode?: 'ceil' | 'floor' | 'expand' | 'trunc' | 'halfCeil' | 'halfFloor' | 'halfExpand' | 'halfTrunc' | 'halfEven';
}

Usage Examples:

// Currency formatting with different display options
const currencySymbol = formatNumber(config, formatters.getNumberFormat, 1234.56, {
  style: 'currency',
  currency: 'EUR',
  currencyDisplay: 'symbol'
});
// Result: "€1,234.56"

const currencyCode = formatNumber(config, formatters.getNumberFormat, 1234.56, {
  style: 'currency', 
  currency: 'EUR',
  currencyDisplay: 'code'
});
// Result: "EUR 1,234.56"

const currencyName = formatNumber(config, formatters.getNumberFormat, 1234.56, {
  style: 'currency',
  currency: 'EUR', 
  currencyDisplay: 'name'
});
// Result: "1,234.56 euros"

// Unit formatting
const distance = formatNumber(config, formatters.getNumberFormat, 15.5, {
  style: 'unit',
  unit: 'kilometer',
  unitDisplay: 'long'
});
// Result: "15.5 kilometers"

const speed = formatNumber(config, formatters.getNumberFormat, 60, {
  style: 'unit',
  unit: 'mile-per-hour',
  unitDisplay: 'short'
});
// Result: "60 mph"

// Scientific notation
const scientific = formatNumber(config, formatters.getNumberFormat, 123456789, {
  notation: 'scientific',
  minimumFractionDigits: 2
});
// Result: "1.23E8"

// Engineering notation
const engineering = formatNumber(config, formatters.getNumberFormat, 123456789, {
  notation: 'engineering',
  minimumFractionDigits: 1
});
// Result: "123.5E6"

Number Parts for Custom Rendering

Use formatNumberToParts for custom styling and rendering.

Usage Examples:

// Currency parts
const currencyParts = formatNumberToParts(config, formatters.getNumberFormat, 1234.56, {
  style: 'currency',
  currency: 'USD'
});

// Result: [
//   { type: 'currency', value: '$' },
//   { type: 'integer', value: '1' },
//   { type: 'group', value: ',' },
//   { type: 'integer', value: '234' },
//   { type: 'decimal', value: '.' },
//   { type: 'fraction', value: '56' }
// ]

// Custom rendering with parts
const customCurrencyRender = currencyParts
  .map(part => {
    if (part.type === 'currency') {
      return `<span class="currency-symbol">${part.value}</span>`;
    }
    if (part.type === 'integer') {
      return `<span class="integer">${part.value}</span>`;
    }
    return part.value;
  })
  .join('');

// Percentage parts with custom styling
const percentParts = formatNumberToParts(config, formatters.getNumberFormat, 0.1234, {
  style: 'percent',
  minimumFractionDigits: 1
});

// Result: [
//   { type: 'integer', value: '12' },
//   { type: 'decimal', value: '.' },
//   { type: 'fraction', value: '3' },
//   { type: 'percentSign', value: '%' }
// ]

// Compact notation parts
const compactParts = formatNumberToParts(config, formatters.getNumberFormat, 1234567, {
  notation: 'compact'
});

// Result: [
//   { type: 'integer', value: '1' },
//   { type: 'decimal', value: '.' },
//   { type: 'fraction', value: '2' },
//   { type: 'compact', value: 'M' }
// ]

Advanced Number Formatting

Precision control, rounding, and locale-specific options.

Usage Examples:

// Significant digits
const significant = formatNumber(config, formatters.getNumberFormat, 123456.789, {
  minimumSignificantDigits: 3,
  maximumSignificantDigits: 5
});
// Result: "123,460" (rounded to 5 significant digits)

// Fraction digit control
const fractions = formatNumber(config, formatters.getNumberFormat, 123.456, {
  minimumFractionDigits: 2,
  maximumFractionDigits: 4
});
// Result: "123.456"

// Accounting currency style
const accounting = formatNumber(config, formatters.getNumberFormat, -1234.56, {
  style: 'currency',
  currency: 'USD',
  currencySign: 'accounting'
});
// Result: "($1,234.56)"

// Always show sign
const alwaysSign = formatNumber(config, formatters.getNumberFormat, 1234, {
  signDisplay: 'always'
});
// Result: "+1,234"

// Custom numbering system
const arabicNumbers = formatNumber(
  { ...config, locale: 'ar-EG' },
  formatters.getNumberFormat,
  1234.56,
  {
    numberingSystem: 'arab'
  }
);
// Result: "١٬٢٣٤٫٥٦"

// Rounding increment (ES2023)
const rounded = formatNumber(config, formatters.getNumberFormat, 1234.567, {
  roundingIncrement: 5,
  minimumFractionDigits: 2
});
// Result: "1,234.55" (rounded to nearest 0.05)

// No grouping
const noGrouping = formatNumber(config, formatters.getNumberFormat, 1234567, {
  useGrouping: false
});
// Result: "1234567"

Custom Number Formats

Define reusable number format configurations.

Usage Examples:

const intl = createIntl({
  locale: 'en-US',
  formats: {
    number: {
      currency: { 
        style: 'currency', 
        currency: 'USD',
        minimumFractionDigits: 2,
        maximumFractionDigits: 2
      },
      percentage: { 
        style: 'percent', 
        minimumFractionDigits: 1,
        maximumFractionDigits: 2
      },
      compact: { 
        notation: 'compact', 
        compactDisplay: 'short',
        maximumFractionDigits: 1
      },
      scientific: {
        notation: 'scientific',
        minimumFractionDigits: 2,
        maximumFractionDigits: 3
      },
      accounting: {
        style: 'currency',
        currency: 'USD',
        currencySign: 'accounting'
      }
    }
  }
});

// Use custom formats
const price = intl.formatNumber(29.99, { format: 'currency' });
// Result: "$29.99"

const growth = intl.formatNumber(0.1567, { format: 'percentage' });
// Result: "15.7%"

const users = intl.formatNumber(1234567, { format: 'compact' });
// Result: "1.2M"

const measurement = intl.formatNumber(0.00012345, { format: 'scientific' });
// Result: "1.235E-4"

const deficit = intl.formatNumber(-1500, { format: 'accounting' });
// Result: "($1,500.00)"

Locale-Specific Number Formatting

Different locales have different number formatting conventions.

Usage Examples:

const value = 1234567.89;

// German locale (period for thousands, comma for decimal)
const german = formatNumber(
  { ...config, locale: 'de-DE' },
  formatters.getNumberFormat,
  value
);
// Result: "1.234.567,89"

// French locale (space for thousands, comma for decimal)
const french = formatNumber(
  { ...config, locale: 'fr-FR' }, 
  formatters.getNumberFormat,
  value
);
// Result: "1 234 567,89"

// Indian locale (different grouping pattern)
const indian = formatNumber(
  { ...config, locale: 'hi-IN' },
  formatters.getNumberFormat,
  value
);
// Result: "12,34,567.89"

// Arabic locale with Arabic-Indic digits
const arabic = formatNumber(
  { ...config, locale: 'ar-SA' },
  formatters.getNumberFormat,
  value,
  { numberingSystem: 'arab' }
);
// Result: "١٬٢٣٤٬٥٦٧٫٨٩"