Чтобы преобразовать строку в число в TypeScript, вызовите Number(text). Результат имеет тип number и равен NaN, если текст не является корректным числом. Для текста с символами в конце, например "42px", используйте parseInt(text, 10) или parseFloat(text).
Все четыре преобразования возвращают тип number. TypeScript не знает, был ли текст корректным; некорректная строка всё равно даёт number, просто его значение равно NaN.
Почему преобразование обязательно
Поля форм, параметры URL, переменные окружения и содержимое файлов приходят строками. TypeScript не даст использовать строку там, где ожидается число:
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.
Арифметика с -, * и / над строкой считается ошибкой. + разрешён, но склеивает строки, поэтому "3" + 10 даёт строку "310". Вот почему сначала нужно преобразование: Number(quantity) * 10.
Утверждение типа тоже не поможет. quantity as number отвергается (TS2352), а если протолкнуть его через as unknown as number, компилятор просто замолчит: во время выполнения значение останется строкой.
Number, parseInt, parseFloat и унарный плюс
На чистых данных все четыре функции дают одно и то же, а во всём остальном расходятся. В таблице реальный вывод каждой из них в Node:
| Ввод | 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 |
Правила, которые стоят за таблицей:
Numberи унарный+работают одинаково. Они преобразуют всю строку после обрезки пробелов, понимают1e3и шестнадцатеричный0xи возвращаютNaN, если что-то осталось. Пустая строка или строка из одних пробелов превращается в0.parseIntиparseFloatчитают с начала и останавливаются на первом символе, который не могут использовать, поэтому"42px"и"1,000"дают частичные числа. Пустая строка даётNaN.parseIntотбрасывает дробную часть и не понимает экспоненту:"1e3"обрывается наe.- Разделители разрядов (
12_000) допустимы в исходном коде, но не в строках.
Для проверки ввода строже Number. parseInt и parseFloat подходят для текста, в котором действительно есть единица измерения или суффикс, например размеров в CSS.
Обработка некорректного ввода: NaN
NaN имеет тип number, поэтому компилятор о нём никогда не предупреждает. Проверяйте результат сами, через Number.isNaN или Number.isFinite:
Возвращаемый тип number | undefined делает ошибку частью типа, и каждый вызывающий код обязан её обработать, прежде чем считать. Number.isFinite к тому же отсекает Infinity, которое Number("Infinity") охотно возвращает.
Избегайте глобального isNaN(x): он сначала преобразует аргумент, поэтому в JavaScript isNaN("abc") равно true. Объявление в TypeScript принимает только number, так что передача строки даёт ошибку TS2345, и это намёк использовать Number.isNaN на уже преобразованном значении.
Строку в целое число
Всегда передавайте parseInt второй аргумент, основание системы счисления: 10 для десятичного текста. Он необязателен, но показывает намерение и важен для других оснований. Чтобы получить целое из десятичной строки, преобразуйте её, а затем явно округлите.
parseInt ожидает строку: parseInt(12.7) даёт ошибку компиляции (TS2345), и это полезно, потому что в JavaScript parseInt сначала превращает число в текст и выдаёт неверные ответы для значений вроде 0.0000005 (возвращает 5). Для чисел используйте Math.trunc. Для целых больше Number.MAX_SAFE_INTEGER BigInt(text) разбирает значение полностью (и на некорректном тексте бросает SyntaxError вместо того, чтобы вернуть NaN).
Число в строку
String(n), n.toString() и `${n}` одинаково превращают число в его кратчайшую строковую форму. Методы форматирования дают больше контроля:
toFixed округляет двоичное значение, а не то десятичное, которое вы написали, поэтому (1.005).toFixed(2) равно "1.00": 1.005 хранится как число чуть меньше 1.005. Для денег храните суммы в целых центах или форматируйте через Intl.NumberFormat.
String(n) работает и с null и undefined (давая "null" и "undefined"), тогда как n.toString() в режиме strict был бы ошибкой компиляции, раз значение может отсутствовать.
Краткая шпаргалка
| Задача | Код | Тип результата |
|---|---|---|
| Строка в число, строго | Number(s) или +s | number (может быть NaN) |
| Целое из начала текста | parseInt(s, 10) | number (может быть NaN) |
| Дробное из начала текста | parseFloat(s) | number (может быть NaN) |
| Проверить результат | Number.isFinite(n), Number.isNaN(n) | boolean |
| Большое целое | BigInt(s) | bigint |
| Число в строку | String(n), n.toString(), `${n}` | string |
| Фиксированное число знаков | n.toFixed(2) | string |
| Другое основание | n.toString(16) | string |
| Разделители тысяч | n.toLocaleString("en-US") | string |
Часто задаваемые вопросы
Как преобразовать строку в число в TypeScript?
Используйте Number(text). Он возвращает number: значение для корректного числового текста, NaN для всего остального и 0 для пустой строки или строки из одних пробелов. Если в тексте могут быть символы в конце, например "42px", используйте parseInt(text, 10) или parseFloat(text).
Можно ли привести строку к числу через as number?
as number?Нет. "42" as number даёт ошибку компиляции (TS2352), и даже если протолкнуть его через unknown, утверждение меняет только тип, который видит компилятор: во время выполнения значение остаётся строкой "42". Преобразуйте значение через Number(), parseInt() или parseFloat().
Чем Number() отличается от parseInt() в TypeScript?
Number преобразует всю строку целиком и возвращает NaN, если какая-то её часть не числовая, поэтому Number("42px") равно NaN. parseInt читает цифры с начала и останавливается на первой нецифре, поэтому parseInt("42px", 10) равно 42, а дробную часть он отбрасывает. Number("") равно 0, а parseInt("") равно NaN.
Как проверить, что строка является корректным числом?
Преобразуйте её и проверьте результат: const n = Number(text); if (text.trim() !== "" && Number.isFinite(n)) { ... }. Проверка на пустую строку важна, потому что Number("") равно 0. Используйте Number.isNaN, а не глобальный isNaN, который TypeScript и так принимает только с аргументом типа number.
Как преобразовать число в строку в TypeScript?
String(n), n.toString() и шаблонный литерал `${n}` дают одинаковый результат. Используйте n.toFixed(2) для фиксированного числа знаков после запятой, n.toString(16) для другой системы счисления и n.toLocaleString("en-US") для разделителей тысяч.