A lightweight utility library for formatting numbers, currencies, percentages, decimals, and more — with full TypeScript support and locale-aware formatting via the Intl
API.
✅ Ideal for dashboards, finance apps, data display, and more.
npm install num-format-utils
# or
yarn add num-format-utils
import {
formatCurrency,
formatCurrencyMatch,
createCurrencyFormatter,
formatDecimal,
formatNumber,
formatPercentage,
formatCompactNumber,
formatUnit,
formatDateTime,
formatRelativeTime,
formatList,
} from "num-format-utils";
Formats a single number as currency using the Intl.NumberFormat API.
value
is provided, defaults to "USD"
and "en-US"
.locale
is provided without currency
, uses the locale’s default currency.locale
and currency
are provided, uses them directly only if the pair is valid.If an invalid locale–currency combination is passed, the function will fallback to the default currency for that locale.
If currency
is passed without locale
, TypeScript will show a type error.
To change the currency signs
e.g (₦787.00 -> “narrowSymbol” by default, NGN 787.00 -> “code”, 787.00 Nigerian nairas -> “name” or NGN 787.00 -> “symbol”)
Simply pass the parameter “currencyDisplay” with any the of following values “narrowSymbol” | “code” | “name” | “symbol” |
formatCurrency({
value: number,
currency?: string,
locale?: string,
currencyDisplay?: "narrowSymbol" | "code" | "name" | "symbol"
}): string
Example:
formatCurrency({ value: 3000 }); // "$3,000.00"
formatCurrency({ value: 3000, currency: "NGN", locale: "en-NG" }); // "₦3,000.00"
formatCurrency({
value: 3000,
currency: "USD",
locale: "en-US",
currencyDisplay: "name",
}); // "3,000.00 US dollars"
Strictly formats a single number as currency using the Intl.NumberFormat API,
requiring an exact locale
–currency
match.
This function is stricter than formatCurrency
:
value
, locale
, and currency
— are required except currencyDisplay which is optional.currency
must match the allowed list for the given locale
.Useful when strict control over formatting is needed — e.g., in finance or compliance-based apps.
To change the currency signs. same as formatCurrency
formatCurrencyMatch({
value: number,
currency: string,
locale: string,
currencyDisplay?: "narrowSymbol" | "code" | "name" | "symbol"
}): string
Example:
formatCurrencyMatch({ value: 3000, locale: "en-NG", currency: "NGN" });
// "₦3,000.00"
formatCurrencyMatch({
value: 3000,
locale: "en-US",
currency: "USD",
currencyDisplay: "name",
}); // "3,000.00 US dollars"
Create a reusable formatter instance for performance.
const ngnFormatter = createCurrencyFormatter("NGN", "en-NG");
ngnFormatter(45000); // "₦45,000.00"
Formats a numeric value to a fixed number of decimal places.
formatDecimal({
value: number,
decimals?: number // default: 2
}): string
Example:
formatDecimal({ value: 123.456 }); // "123.46"
formatDecimal({ value: 1000, decimals: 3 }); // "1000.000"
Formats a numeric value using locale-specific digit grouping and decimal separators.
formatNumber({
value: number,
locale?: string
}): string
Example:
formatNumber({ value: 1000000 }); // "1,000,000"
formatNumber({ value: 1000000, locale: "de-DE" }); // "1.000.000"
Formats a numeric value as a percentage string.
%
sign, with optional control over the number of decimal places.formatPercentage({
value: number,
fractionDigits?: number
}): string
Example:
formatPercentage({ value: 0.65 }); // "65.00%"
formatPercentage({ value: 0.1, fractionDigits: 0 }); // "10%"
Formats a number using the Intl.NumberFormat
API with either “compact” or “standard” notation.
"compact"
Formats numbers using abbreviations (e.g. 1K, 2.3M, 6.5 thousand)."standard"
Formats numbers using regular locale-specific formatting (e.g., 1,000, 1,650,000).formatCompactNumber({
value: number,
locale?: string,
notation?: "compact" | "standard",
compactDisplay?: "short" | "long"
}): string;
Example:
formatCompactNumber({ value: 1000 }); // 1K
formatCompactNumber({ value: 1000, notation: "standard" }); // "1,000"
formatCompactNumber({ value: 6500, locale: "en-NG", compactDisplay: "long" });
("6.5 thousand");
format a number using the Intl unit style e.g (“day”, “year”, “month”, “kilogram”) etc.
formatUnit({
value: number,
unit: string,
locale?: string,
unitDisplay?: "long" | "short" | "narrow"
}): string;
Example:
formatUnit({ value: 150 }); by default if no other options are passed // "150 kg"
formatUnit({ value: 12, unit: "minute", unitDisplay: "short" }); // "12 min"
formatUnit({ value: 10, unit: "year", unitDisplay: "short" }); // "10 yrs"
formatUnit({ value: 120, unit: "kilobyte", unitDisplay: "short" }); // "120 kB"
Formats a date or timestamp into a localized string using Intl.DateTimeFormat.
formatDateTime({
date: Date | string | number,
locale?: string,
options?: "short" | "long" | "dateOnly" | "timeOnly" | "full" | Intl.DateTimeFormatOptions
}): string
Example:
formatDateTime({ date: "2025-07-15T08:00:00Z" });
// "July 15, 2025 at 8:00:00 AM"
formatDateTime({ date: Date.now(), options: "short" }); // "07/15/25, 10:04"
formatDateTime({
date: Date.UTC(2012, 11, 20, 3, 0, 0, 200),
locale: "en-AU",
options: {
timeZone: "Australia/Sydney",
timeZoneName: "short",
},
}); // 20/12/2012, AEDT
formatDateTime({ date: "abc" }); // (and logs a warning)
Formats time relative to the current time (e.g. “in 3 days”, “2 hours ago”).
formatRelativeTime({
value: number,
unit?: Intl.RelativeTimeFormatUnit,
locale?: string,
plain?: boolean,
numeric?: "auto" | "always",
style?: "short" | "long" | "narrow"
}): string
Example:
formatRelativeTime({ value: -1 }); // "1 day ago"
formatRelativeTime({ value: -5, plain: true }); // "5 days" (strips "ago"/"in")
formatRelativeTime({ value: "abc" }); // "" (with warning)
Formats an array of strings into a localized, human-readable list using Intl.ListFormat.
Oxford comma: is a comma placed immediately before the coordinating conjunction (usually “and” or “or”) in a list of three or more terms. Somewhat controversially, the en-US locale uses the Oxford comma, while the en-GB locale does not.
formatList({
items: string[],
locale?: string,
style?: "long" | "short" | "narrow",
type?: "conjunction" | "disjunction"
}): string
Example:
formatList({ items: ["Apples", "Bananas", "Cherries"] });
// "Apples, Bananas, and Cherries"
formatList({ items: ["Apples", "Bananas", "Cherries"], locale: "en-US" type: "disjunction" });
// "Apples, Bananas, or Cherries" - locale = "en-US" uses the oxford comma
formatList({ items: ["Apples", "Bananas", "Cherries"], locale: "en-GB" type: "disjunction" });
// "Apples, Bananas or Cherries" - locale = "en-GB" does not use the oxford comma
Contributions are welcome! Please open an issue or submit a pull request with your suggestions or improvements.
MIT © Justice Chimobi