JS / Основы
Преобразование типов в JavaScript: Number, String, Boolean и частые ловушки
Явное и неявное преобразование типов, NaN, truthy и falsy, данные форм, операторы ?? и || и безопасные проверки.
Содержание статьи
JavaScript может преобразовывать значения автоматически, но неявные правила иногда дают неожиданный результат. На границах системы — в формах, URL, JSON и data-* — лучше преобразовывать тип явно и сразу проверять итог.
const quantityText = '3';const quantity = Number(quantityText);if (!Number.isInteger(quantity) || quantity < 1) { throw new TypeError('Количество должно быть положительным целым числом');}Основные типы
Примитивы JavaScript:
string;number;bigint;boolean;undefined;symbol;null— отдельное примитивное значение, хотяtypeof nullисторически возвращает'object'.
Объекты, массивы и функции относятся к ссылочным значениям.
typeof '42'; // 'string'typeof 42; // 'number'typeof 42n; // 'bigint'typeof null; // 'object' — историческая особенностьArray.isArray([]); // trueДля массива используйте Array.isArray(), для null — прямое сравнение.
Преобразование в строку
String(42); // '42'String(true); // 'true'String(null); // 'null'String(undefined); // 'undefined'В шаблонной строке преобразование происходит автоматически:
const count = 5;const message = `Найдено: ${count}`;Для отображения чисел и дат используйте Intl, а не простое преобразование:
const formatted = new Intl.NumberFormat('ru-RU', { style: 'currency', currency: 'RUB',}).format(1299.5);Преобразование в число
Number('42'); // 42Number(' 42 '); // 42Number(''); // 0Number('12px'); // NaNNumber(null); // 0Number(undefined); // NaNПустая строка превращается в 0, поэтому обязательное поле сначала проверяют как строку:
function parseRequiredNumber(value) { if (typeof value !== 'string' || value.trim() === '') { return null; } const number = Number(value); return Number.isFinite(number) ? number : null;}parseInt() и parseFloat()
Эти функции читают числовое начало строки:
Number.parseInt('42px', 10); // 42Number.parseFloat('3.14rem'); // 3.14Number('42px'); // NaNДля валидации целиком введённого числа обычно лучше Number(). parseInt() полезен, когда формат намеренно допускает суффикс. Всегда указывайте основание 10.
NaN
NaN имеет тип number и не равен самому себе:
typeof NaN; // 'number'NaN === NaN; // falseПроверяйте через Number.isNaN() или, чаще, через Number.isFinite():
const result = Number('abc');Number.isNaN(result); // trueNumber.isFinite(result); // falseГлобальная isNaN() сама преобразует аргумент и потому менее предсказуема.
BigInt
const identifier = BigInt('9007199254740993');BigInt хранит целые числа произвольной точности, но его нельзя напрямую смешивать с number:
1n + 1; // TypeErrorJSON не сериализует BigInt стандартным JSON.stringify() без явного преобразования. Выбирайте тип с учётом источника и способа передачи данных.
Boolean, truthy и falsy
Falsy-значения:
false0-00n"" (пустая строка)nullundefinedNaNОстальные значения truthy, включая строки '0' и 'false', пустой массив и пустой объект.
Boolean('false'); // trueBoolean([]); // trueBoolean({}); // trueЕсли API прислал строку 'false', преобразуйте по явному allowlist:
function parseBoolean(value) { if (value === 'true') return true; if (value === 'false') return false; return null;}|| и ??
|| выбирает правую часть для любого falsy-значения:
const quantity = 0;quantity || 1; // 1 — ноль потерян.quantity ?? 1; // 0 — ноль сохранён.Оператор ?? использует fallback только для null и undefined. Он лучше подходит, когда 0, false и пустая строка являются допустимыми значениями.
Строгое и нестрогое равенство
0 == false; // true из-за преобразования0 === false; // falseВ прикладном коде используйте === и !==. Редкое осознанное исключение — value == null, которое одновременно проверяет null и undefined, но явная запись обычно читается лучше:
value === null || value === undefined;Значения HTML-форм
Большинство значений формы приходят строками:
const form = document.querySelector('#order-form');const data = new FormData(form);const quantityRaw = data.get('quantity');const quantity = typeof quantityRaw === 'string' ? parseRequiredNumber(quantityRaw) : null;FormData.get() также может вернуть File или null, поэтому нельзя без проверки вызывать строковые методы.
У <input type="number"> есть valueAsNumber, но пустое или неверное значение даёт NaN:
const field = document.querySelector('#quantity');if (field && Number.isFinite(field.valueAsNumber)) { console.log(field.valueAsNumber);}Данные из dataset
Значения data-* всегда строки:
<div data-page="3" data-enabled="false"></div>const element = document.querySelector('[data-page]');const page = Number.parseInt(element.dataset.page, 10);const enabled = element.dataset.enabled === 'true';Проверяйте результат так же, как любой внешний ввод.
Что запомнить
Преобразуйте типы явно на границе получения данных. После Number() проверяйте конечность и диапазон, не считайте строку 'false' ложной, используйте ??, когда ноль и пустая строка допустимы, и предпочитайте строгое равенство. Типизация не заменяет валидацию смысла.