How to Format Numbers with Commas in TypeScript

The quickest way to format numbers with commas in TypeScript is value.toLocaleString("en-US"). It returns a string with a comma between every group of three digits, so 1284567.5 becomes “1,284,567.5”:

const display = revenue.toLocaleString("en-US");   // "1,284,567.5"

Nothing below is hand-typed output: I pasted each result from TypeScript 7.0.2 and Node.js v22.22.2, compiling with --strict turned on.

Below, I’ll cover toLocaleString, a reusable Intl.NumberFormat, decimals, a regex fallback, compact labels like 1.3M, and turning a formatted string back into a number.

Add commas with toLocaleString()

Always pass the locale. Without it, the result follows the browser or server settings, so a user in Germany sees periods where you expected commas. toLocaleString() also works on bigint:

const population: number = 39431263;
const revenue: number = 1284567.5;
const bigTotal: bigint = 36218604000000n;

console.log(population.toLocaleString("en-US"));
console.log(revenue.toLocaleString("en-US"));
console.log(bigTotal.toLocaleString("en-US"));
console.log(revenue.toLocaleString("de-DE"));   // German separators

Output:

39,431,263
1,284,567.5
36,218,604,000,000
1.284.567,5

Remember that the result is a string, meant for display only. If you only need plain digits without grouping, converting a number to a string in TypeScript is the simpler route.

Use Intl.NumberFormat for repeated formatting

toLocaleString() builds a formatter on every call. When you format a whole table or list, create one Intl.NumberFormat and reuse its format() method. It’s faster and keeps the options in one place:

const withCommas = new Intl.NumberFormat("en-US");
const twoDecimals = new Intl.NumberFormat("en-US", {
  minimumFractionDigits: 2,
  maximumFractionDigits: 2,
});

const amounts: number[] = [1234.5678, 98765.4, 2500000, -45210.999];
for (const n of amounts) {
  console.log(String(n).padEnd(12), withCommas.format(n).padEnd(12), twoDecimals.format(n));
}
console.log("no grouping:", new Intl.NumberFormat("en-US", { useGrouping: false }).format(2500000));

Output:

1234.5678    1,234.568    1,234.57
98765.4      98,765.4     98,765.40
2500000      2,500,000    2,500,000.00
-45210.999   -45,210.999  -45,211.00
no grouping: 2500000
Command Prompt output of TypeScript Intl.NumberFormat adding commas to numbers with and without two fixed decimals
Default grouping, the same values with exactly two decimals, and useGrouping: false turning commas off.

Look at the first row. With no options, maximumFractionDigits defaults to 3, so 1234.5678 is rounded to “1,234.568”. That catches people who expect every digit to survive.

The array loop here is a simple for...of; to build a new array of labels, use map() as shown in mapping an array of objects in TypeScript.

How do you format decimals with commas?

Set minimumFractionDigits and maximumFractionDigits to the same number, as in twoDecimals above. You get commas and a fixed decimal count in one step, with 2500000 showing as “2,500,000.00”. For zero-padding and toFixed(), see formatting a number to 2 digits in TypeScript.

Don’t chain toFixed(2) before toLocaleString(), though. toFixed() returns a string, and a string can’t be grouped like a number, so you’d lose the commas.

Add thousands separators with a regex

A regular expression gives you commas without the Intl API, which is handy for fixed-format exports. The popular one-liner has a bug with decimals, so compare it with the fixed version:

function addCommasNaive(value: number): string {
  return value.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}

function addCommas(value: number): string {
  const [whole, fraction] = value.toString().split(".");
  const grouped = whole.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
  return fraction === undefined ? grouped : `${grouped}.${fraction}`;
}

console.log("naive:", addCommasNaive(8405837), addCommasNaive(-1234567), addCommasNaive(1234.5678));
console.log("fixed:", addCommas(8405837), addCommas(-1234567), addCommas(1234.5678));

Output:

naive: 8,405,837 -1,234,567 1,234.5,678
fixed: 8,405,837 -1,234,567 1,234.5678
Command Prompt output of a TypeScript regex adding thousands separators, with the naive version wrongly grouping decimal digits
The naive regex turns 1234.5678 into “1,234.5,678”; splitting on the decimal point fixes it.

The fix formats only the whole-number part, then glues the fraction back on. Negatives work because \B never matches right after the minus sign. More on replace() patterns is in replacing all occurrences of a substring in TypeScript.

Common TypeScript errors with formatted numbers

The formatted value is a string, and strict mode won’t let you treat it as a number. A misspelled option is caught too:

const miles: number = 2789.6;

const total: number = miles.toLocaleString("en-US");
const doubled = miles.toLocaleString("en-US") * 2;
const label = new Intl.NumberFormat("en-US", { maximumFractionDigit: 1 }).format(miles);

Output:

commas_types.ts(3,7): error TS2322: Type 'string' is not assignable to type 'number'.
commas_types.ts(4,17): error TS2362: The left-hand side of an arithmetic operation must be of type 'any', 'number', 'bigint' or an enum type.
commas_types.ts(5,48): error TS2769: No overload matches this call.
  The last overload gave the following error.
    Object literal may only specify known properties, but 'maximumFractionDigit' does not exist in type 'NumberFormatOptions'. Did you mean to write 'maximumFractionDigits'?
Command Prompt showing TypeScript errors TS2322, TS2362 and TS2769 when using a toLocaleString string as a number
TS2322 and TS2362 flag the string-as-number mistakes; TS2769 catches maximumFractionDigit and suggests the right name.

Keep the raw number for math and sorting, and format only when you display it.

Compact numbers and parsing commas back

For dashboards, notation: "compact" turns 1,250,000 into “1.3M”. Going the other way, Number() returns NaN for “1,234.56”, so strip the separators first.

I read the separators from formatToParts(), so one function handles German input too. Other string-to-number cases are in converting a string to a double in TypeScript.

const compact = new Intl.NumberFormat("en-US", { notation: "compact", maximumFractionDigits: 1 });
for (const views of [950, 12_400, 1_250_000, 3_800_000_000]) {
  console.log(views.toLocaleString("en-US").padStart(13), "->", compact.format(views));
}

console.log('Number("1,234.56"):', Number("1,234.56"));

function parseLocaleNumber(text: string, locale = "en-US"): number {
  const parts = new Intl.NumberFormat(locale).formatToParts(12345.6);
  const group = parts.find((p) => p.type === "group")?.value ?? ",";
  const decimal = parts.find((p) => p.type === "decimal")?.value ?? ".";
  return Number(text.replaceAll(group, "").replace(decimal, "."));
}

console.log("en-US:", parseLocaleNumber("1,234,567.89"));
console.log("de-DE:", parseLocaleNumber("1.234.567,89", "de-DE"));

Output:

          950 -> 950
       12,400 -> 12.4K
    1,250,000 -> 1.3M
3,800,000,000 -> 3.8B
Number("1,234.56"): NaN
en-US: 1234567.89
de-DE: 1234567.89
Command Prompt output of TypeScript compact number notation and parsing comma-formatted strings back to numbers
Compact labels like 12.4K and 3.8B, NaN from a plain Number() call, and the locale-aware parser.

Validate user input before parsing; checking if a string is a number in TypeScript covers that.

Which way to add commas in TypeScript should you use?

MethodBest forWatch out for
toLocaleString("en-US")One-off values, bigintOmitting the locale
Intl.NumberFormatTables, lists, fixed decimalsDefault 3-digit rounding
RegexFixed-format exportsDecimals; split on . first
notation: "compact"Dashboards and labelsIt drops precision

I reach for Intl.NumberFormat in nearly every app and keep the regex for the rare case where the output must never change with the locale.

Want to keep going? These guides pair well with this one:

Frequently asked questions

How do I format a number with commas in TypeScript?

Call n.toLocaleString("en-US") or new Intl.NumberFormat("en-US").format(n). Both return a string like “1,234,567”.

Why does toLocaleString() show periods instead of commas?

No locale was passed, so the runtime’s default locale was used. Pass "en-US" explicitly for comma grouping.

How do I keep two decimals and add commas?

Use Intl.NumberFormat with minimumFractionDigits: 2 and maximumFractionDigits: 2.

How do I remove commas from a number string?

Use Number(text.replaceAll(",", "")) for US input, or read the separators from formatToParts() for other locales.

Does toLocaleString() work with bigint?

Yes. BigInt values have their own toLocaleString(), so 36218604000000n prints as “36,218,604,000,000”.

Where are the Intl.NumberFormat options documented?