You can use a function like this one to wrap toLocaleString
:
const currencyToString = (
num, {
locale = "en-US",
currency = "USD",
minimumFractionDigits = 2,
maximumFractionDigits,
abbreviationFormats
}
) => {
if (num == null || typeof num !== "number") {
// null, undefined, non-numeric, return what was provided
return num;
}
let format;
if (abbreviationFormats != null) {
// formats were provided, find one that works
format = abbreviationFormats.find(f => num >= f.value);
}
if (format != null) {
// apply the format, insert the symbol next to the numeric portion of the formatted string
const {
value,
symbol
} = format;
const formatted = (num / value).toLocaleString(locale, {
style: "currency",
currency,
minimumFractionDigits,
maximumFractionDigits
});
const parts = formatted.match(/([\D]*)([\d.,]+)([\D]*)/)
return `${parts[1]}${parts[2]}${symbol}${parts[3]}`
}
// otherwise, use the number as provided
return num.toLocaleString(locale, {
style: "currency",
currency,
minimumFractionDigits,
maximumFractionDigits
});
};
This will accept an optional structure of formats that can be used to abbreviate large numbers:
const formats = [
{ value: 1e12, symbol: "T" },
{ value: 1e9, symbol: "B" },
{ value: 1e6, symbol: "M" },
{ value: 1e3, symbol: "K" }
];
Here is a codesandbox with a lot of tests with a few combinations of locale
and currency
.