To convert a string to a number in TypeScript, call Number(text). The result has type number, and it is NaN when the text is not a valid number. For text with trailing characters, such as "42px", use parseInt(text, 10) or parseFloat(text).
All four conversions return the type number. TypeScript does not know whether the text was valid; an invalid string still gives a number, whose value is NaN.
Why You Must Convert
Form fields, URL parameters, environment variables and file contents arrive as strings. TypeScript will not let you use one where a number is expected:
index.ts(3,23): error TS2362: The left-hand side of an arithmetic operation must be of type 'any', 'number', 'bigint' or an enum type.
Arithmetic with -, * and / on a string is an error. + is allowed but concatenates, so "3" + 10 is the string "310", which is why the conversion must come first: Number(quantity) * 10.
A type assertion does not help either. quantity as number is rejected (TS2352), and forcing it through as unknown as number only silences the compiler: the value stays a string at runtime.
Number vs parseInt vs parseFloat vs Unary Plus
The four functions agree on clean input and disagree on everything else. This table is the real output of each on Node:
| Input | Number(s) | +s | parseInt(s, 10) | parseFloat(s) |
|---|---|---|---|---|
"42" | 42 | 42 | 42 | 42 |
"3.99" | 3.99 | 3.99 | 3 | 3.99 |
"42px" | NaN | NaN | 42 | 42 |
"" | 0 | 0 | NaN | NaN |
" 3 " | 3 | 3 | 3 | 3 |
"1e3" | 1000 | 1000 | 1 | 1000 |
"0x1F" | 31 | 31 | 0 | 0 |
"1,000" | NaN | NaN | 1 | 1 |
"12_000" | NaN | NaN | 12 | 12 |
"abc" | NaN | NaN | NaN | NaN |
The rules behind the table:
Numberand unary+are identical. They convert the whole string after trimming whitespace, understand1e3and0xhex, and returnNaNif anything is left over. An empty or whitespace-only string becomes0.parseIntandparseFloatread from the start and stop at the first character they cannot use, so"42px"and"1,000"give partial numbers. An empty string isNaN.parseIntdrops the fractional part and does not understand exponents:"1e3"stops at thee.- Numeric separators (
12_000) are valid in source code, not in strings.
Number is the stricter choice for validating input. parseInt and parseFloat suit text that genuinely carries a unit or suffix, like CSS sizes.
Handling Invalid Input: NaN
NaN has type number, so the compiler never warns about it. Check the result yourself, with Number.isNaN or Number.isFinite:
Returning number | undefined makes the failure part of the type, so every caller must handle it before doing arithmetic. Number.isFinite also rejects Infinity, which Number("Infinity") happily returns.
Avoid the global isNaN(x): it converts its argument first, so isNaN("abc") is true in JavaScript. TypeScript's declaration only accepts a number, so passing a string is error TS2345, which is a hint to use Number.isNaN on an already converted value.
String to Integer
Always pass parseInt its second argument, the radix: 10 for decimal text. It is optional, but it documents intent and matters for other bases. To get an integer from a decimal string, convert and then round explicitly.
parseInt expects a string: parseInt(12.7) is a compile error (TS2345), which is useful, because in JavaScript parseInt on a number converts it to text first and gives wrong answers for values like 0.0000005 (it returns 5). Use Math.trunc for numbers. For integers beyond Number.MAX_SAFE_INTEGER, BigInt(text) parses the full value (and throws a SyntaxError on invalid text instead of returning NaN).
Number to String
Any of String(n), n.toString() and `${n}` converts a number to its shortest string form. Formatting methods give more control:
toFixed rounds the binary value, not the decimal you typed, so (1.005).toFixed(2) is "1.00": 1.005 is stored as slightly less than 1.005. For money, keep amounts as integer cents or format with Intl.NumberFormat.
String(n) also works on null and undefined (giving "null" and "undefined"), where n.toString() would be a compile error under strict, since the value might be missing.
Quick Reference
| Task | Code | Result type |
|---|---|---|
| String to number, strict | Number(s) or +s | number (maybe NaN) |
| Leading integer from text | parseInt(s, 10) | number (maybe NaN) |
| Leading decimal from text | parseFloat(s) | number (maybe NaN) |
| Check the result | Number.isFinite(n), Number.isNaN(n) | boolean |
| Big integer | BigInt(s) | bigint |
| Number to string | String(n), n.toString(), `${n}` | string |
| Fixed decimals | n.toFixed(2) | string |
| Other base | n.toString(16) | string |
| Thousands separators | n.toLocaleString("en-US") | string |
Frequently Asked Questions
How do I convert a string to a number in TypeScript?
Use Number(text). It returns a number: the value for valid numeric text, NaN for anything else, and 0 for an empty or whitespace-only string. Use parseInt(text, 10) or parseFloat(text) when the text may have trailing characters such as "42px".
Can I cast a string to a number with as number?
as number?No. "42" as number is a compile error (TS2352), and even when forced through unknown, an assertion changes only the type the compiler sees: the value is still the string "42" at runtime. Convert the value with Number(), parseInt() or parseFloat().
What is the difference between Number() and parseInt() in TypeScript?
Number converts the whole string and returns NaN if any part is not numeric, so Number("42px") is NaN. parseInt reads digits from the start and stops at the first non-digit, so parseInt("42px", 10) is 42, and it drops decimals. Number("") is 0, while parseInt("") is NaN.
How do I check if a string is a valid number?
Convert it and test the result: const n = Number(text); if (text.trim() !== "" && Number.isFinite(n)) { ... }. The empty-string check matters because Number("") is 0. Use Number.isNaN, not the global isNaN, which TypeScript only accepts with a number argument anyway.
How do I convert a number to a string in TypeScript?
String(n), n.toString() or a template literal `${n}` all give the same result. Use n.toFixed(2) for a fixed number of decimals, n.toString(16) for another base, and n.toLocaleString("en-US") for thousands separators.