You can get the decimal part of a number in TypeScript with the remainder operator: x % 1 returns everything after the decimal point as a number. For 24.75 that’s 0.75, and an integer gives 0:
const fraction = price % 1; // 24.75 -> 0.75
My test machine runs TypeScript 7.0.2 and Node.js v22.22.2; I built each file with strict checks on and copied the real console output under it.
Get the decimal part with % 1 or Math.trunc()
The remainder of dividing by 1 is the fraction. Subtracting the whole part, x - Math.trunc(x), gives the same result, and Math.trunc() on its own hands you the integer part:
const price: number = 24.75;
const viaRemainder = price % 1;
const viaTrunc = price - Math.trunc(price);
const wholePart = Math.trunc(price);
console.log("price % 1 :", viaRemainder);
console.log("price - trunc(price):", viaTrunc);
console.log("whole part :", wholePart);
console.log("is 42 an integer? :", Number.isInteger(42), "->", 42 % 1);
Output:
price % 1 : 0.75
price - trunc(price): 0.75
whole part : 24
is 42 an integer? : true -> 0
I reach for % 1 when I only need the fraction, and the Math.trunc() pair when I also want whole dollars or units. Got the value as text? Convert it with string to number conversion in TypeScript.
For an integer check, Number.isInteger(x) reads better than x % 1 === 0, and it narrows nicely with type narrowing in TypeScript.
How do negative numbers change the decimal part?
Here the methods split. % keeps the sign of the left operand and Math.trunc() cuts toward zero, so both give a negative fraction. Math.floor() rounds toward negative infinity, so it gives a positive one:
const values: number[] = [3.75, -3.75, -0.5, -5];
for (const x of values) {
console.log(
String(x).padStart(5),
"| % 1:", String(x % 1).padStart(5),
"| x - trunc:", String(x - Math.trunc(x)).padStart(5),
"| x - floor:", String(x - Math.floor(x)).padStart(4),
"| abs(% 1):", Math.abs(x % 1),
);
}
console.log("Object.is(-5 % 1, -0):", Object.is(-5 % 1, -0));
Output:
3.75 | % 1: 0.75 | x - trunc: 0.75 | x - floor: 0.75 | abs(% 1): 0.75
-3.75 | % 1: -0.75 | x - trunc: -0.75 | x - floor: 0.25 | abs(% 1): 0.75
-0.5 | % 1: -0.5 | x - trunc: -0.5 | x - floor: 0.5 | abs(% 1): 0.5
-5 | % 1: 0 | x - trunc: 0 | x - floor: 0 | abs(% 1): 0
Object.is(-5 % 1, -0): true

% 1 and trunc give -0.75, while floor gives 0.25. Math.abs() returns the plain digits.Pick by meaning: Math.abs(x % 1) for the digits after the point, or x - Math.floor(x) when you need a value in [0, 1).
One oddity: -5 % 1 is actually -0, as Object.is shows. It equals 0 with ===, so it rarely matters.
Why is the decimal part of 3.14 not exactly 0.14?
TypeScript numbers are 64-bit binary floats, so most decimal fractions aren’t stored exactly. Removing the whole part exposes the error that console.log(3.14) hides:
const samples: number[] = [3.14, 1.37, 19.99, 1234.56];
for (const x of samples) {
console.log(`${x} % 1 =`, x % 1);
}
function decimalPart(x: number, digits = 2): number {
const frac = x % 1;
const factor = 10 ** digits;
return Math.round(frac * factor) / factor;
}
console.log("decimalPart(3.14) :", decimalPart(3.14));
console.log("decimalPart(-3.14) :", decimalPart(-3.14));
console.log("typeof (3.14 % 1).toFixed(2) :", typeof (3.14 % 1).toFixed(2));
console.log("(1.005).toFixed(2) :", (1.005).toFixed(2));
Output:
3.14 % 1 = 0.14000000000000012
1.37 % 1 = 0.3700000000000001
19.99 % 1 = 0.9899999999999984
1234.56 % 1 = 0.5599999999999454
decimalPart(3.14) : 0.14
decimalPart(-3.14) : -0.14
typeof (3.14 % 1).toFixed(2) : string
(1.005).toFixed(2) : 1.00

Round to the digits you care about. My decimalPart() helper returns a number; toFixed(2) returns a string, so wrap it in Number() for more math. More rounding options are in rounding to 2 decimal places in TypeScript.
Watch the last line: (1.005).toFixed(2) gives "1.00", because 1.005 is really stored as 1.00499999… Don’t treat toFixed as a money calculator.
Decimal part of a string: the TS2362 error
Form, CSV and query-string values are strings, and TypeScript won’t let you use % on them. You’ll see this:
const fromForm: string = "19.99"; // value from an input field
const cents = fromForm % 1;
Output:
decimal_string_error.ts(3,15): error TS2362: The left-hand side of an arithmetic operation must be of type 'any', 'number', 'bigint' or an enum type.

Parse it with Number() or parseFloat() first. I compare those in converting a string to a double in TypeScript, and checking whether a string is a number catches bad input.
Get the decimal digits as a string with split(‘.’)
Sometimes you want the digits as text, like "05" for 8.05. Splitting String(x) on the dot does that, with sharp edges:
function decimalDigits(x: number): string {
const [, digits = ""] = String(x).split(".");
return digits;
}
console.log("24.75 ->", decimalDigits(24.75));
console.log("8.05 ->", decimalDigits(8.05));
console.log("12 ->", JSON.stringify(decimalDigits(12)));
console.log("1.5e-7 ->", decimalDigits(1.5e-7), " String():", String(1.5e-7));
console.log("2.5e21 ->", JSON.stringify(decimalDigits(2.5e21)), " String():", String(2.5e21));
const german = (1234.56).toLocaleString("de-DE");
console.log("de-DE text:", german, "->", german.split(".")[1]);
const safe = (x: number) => x.toFixed(2).split(".")[1];
console.log("toFixed(2) split:", safe(1.5e-7), safe(1234.56));
Output:
24.75 -> 75
8.05 -> 05
12 -> ""
1.5e-7 -> 5e-7 String(): 1.5e-7
2.5e21 -> "5e+21" String(): 2.5e+21
de-DE text: 1.234,56 -> 234,56
toFixed(2) split: 00 56
Three results are wrong. Tiny and huge values switch to exponent notation, so 1.5e-7 yields "5e-7" and 2.5e21 yields "5e+21". And German toLocaleString() output uses a comma, so the split grabs the wrong piece.
If you need text, fix the digits first: x.toFixed(2).split(".")[1] never uses exponent notation for values under 1e21. For display formatting, see formatting numbers with 2 digits in TypeScript.
Get cents from a USD amount with integer math
Money is where decimal noise bites. Truncating the fraction times 100 loses a cent on common prices, so it’s safer to convert the whole amount to integer cents once:
const amounts: number[] = [19.99, 4.35, 1250.1, 0.07];
for (const usd of amounts) {
const naiveCents = Math.trunc((usd % 1) * 100);
const totalCents = Math.round(usd * 100); // whole cents as an integer
const dollars = Math.trunc(totalCents / 100);
const cents = totalCents % 100;
console.log(
`${("$" + usd.toFixed(2)).padStart(9)} naive: ${String(naiveCents).padStart(2)}`,
` dollars: ${String(dollars).padStart(4)} cents: ${String(cents).padStart(2, "0")}`,
);
}
Output:
$19.99 naive: 98 dollars: 19 cents: 99
$4.35 naive: 34 dollars: 4 cents: 35
$1250.10 naive: 9 dollars: 1250 cents: 10
$0.07 naive: 7 dollars: 0 cents: 07

My rule: Math.round(usd * 100) as soon as a price arrives, do the math in integer cents, and format at the end. I do the same when totaling carts with the TypeScript array reduce method.
Ways to get the decimal part in TypeScript compared
| Approach | Result for -3.75 | Use it when |
|---|---|---|
x % 1 | -0.75 | You want the fraction with the same sign |
x - Math.trunc(x) | -0.75 | You also need the whole part |
x - Math.floor(x) | 0.25 | You need a value in [0, 1) |
Math.abs(x % 1) | 0.75 | You want the plain digits |
Math.round(x * 100) % 100 | -75 | Cents from a money amount |
Here are a few more number guides worth a look:
- Format a number with commas in TypeScript
- Convert a number to a string with leading zeros
- Get the string after a character in TypeScript
Frequently asked questions
How do I get the decimal part of a number in TypeScript?
Use x % 1. It returns 0.75 for 24.75 and 0 for an integer.
Why is the decimal part negative for negative numbers?
% keeps the sign of the left operand, so -3.75 % 1 is -0.75. Wrap it in Math.abs() if you don’t want the sign.
How do I remove floating-point noise like 0.14000000000000012?
Round to the digits you need: Math.round(frac * 100) / 100, or Number(frac.toFixed(2)).
How do I get the cents from a dollar amount?
Use Math.round(usd * 100) % 100. Don’t truncate the raw fraction times 100.
Is splitting the string on the dot safe?
Not on its own. String() uses exponent notation for tiny or huge values. Call toFixed() first.
Where is the remainder operator documented?
See Remainder (%) on MDN.

Bijay Kumar is a 13-time Microsoft MVP with more than 18 years in software development, and the founder of Python Guides and TSinfo Technologies. He started out building .NET and SharePoint solutions at HP, TCS and KPIT before moving into Python, machine learning and AI, and he also builds web apps with TypeScript and React. He writes the tutorials here himself, and every example is run before publishing so you see the real output. More about Bijay · Microsoft MVP profile · LinkedIn