Булевый тип Boolean — самый компактный в JavaScript. Всего два значения: true и false. Литералы пишутся в нижнем регистре, без кавычек, и обычно появляются в логических выражениях:

let isLoggedIn = true;
let hasError = false;
let canSubmit = isLoggedIn && !hasError;
let isAdult = age >= 18;
let isOpen = element.classList.contains('open');

Несмотря на «всего два значения», булевый — один из самых частых типов в коде. Каждое if, каждый тернарник, каждый цикл по условию — всё построено на булевых. И именно поэтому конверсии «в булевое» и «из булевого» постоянно встречаются.

Зачем превращать булевое во что-то ещё

В чистом коде булевое живёт само в себе и нигде не пересекается с другими типами. Но как только начинаются эффекты во внешнем мире — начинаются преобразования.

  • localStorage. Хранилище принимает только строки — localStorage.setItem('flag', true) положит туда "true", не true. При чтении нужно явно сравнивать с "true", иначе любая непустая строка превратится в true через прямой Boolean(x).
  • API-форматы. Часть бэкендов вместо true/false ждёт 1/0 (наследие SQL и протоколов вроде MQTT). Перед отправкой делается Number(flag).
  • HTML-атрибуты. aria-pressed, aria-expanded и подобные принимают именно строки "true"/"false". Прямое присвоение булевого в атрибут даёт ту же строку, но через String(flag) читается лучше.
  • Арифметика над флагами. Считать «сколько чекбоксов отмечено» удобно через arr.filter(x => x).length, но иногда — через сложение: true + true + false === 2. Это уже автоматическое преобразование к числу.
  • Сериализация и логи. При выводе в DOM или в консоль true отображается как строка "true" — JavaScript подставляет toString() сам.

Пять направлений преобразования

Из булевого можно получить любой другой тип. Большинство кейсов разбирается в отдельных главах — ниже короткий обзор, чтобы держать в голове общую картину.

  • Булевое в строкуString(flag) или flag.toString(). Оба возвращают "true" или "false". Шаблонный литерал `${flag}` делает то же самое.
  • Булевое в числоNumber(true) === 1, Number(false) === 0. Унарный плюс +true делает то же. Удобно для подсчёта truthy-значений в массиве.
  • Булевое в массив[flag] просто оборачивает значение в одноэлементный массив. Семантически странный случай (чаще нужно «собрать массив флагов»), но иногда требуется для унификации интерфейса.
  • Булевое в объектnew Boolean(flag) создаёт объект-обёртку. В современном коде почти не нужен — примитив сам «боксится», когда вызываешь у него метод. Один из редких случаев — интероп со старым кодом, ожидающим именно объект.
  • Булевое в специальное значениеnull, undefined, NaN. Делается тернарником, когда нужно «стереть» флаг.

Truthy и falsy — шесть значений на запоминание

В JavaScript любое значение можно использовать в условии: if (x). Движок сам неявно превратит его в булевое. Список falsy-значений строго определён — их шесть штук:

false                  // false
0, -0, 0n              // false (ноль обычный, ноль отрицательный, ноль BigInt)
""                     // false (пустая строка)
null                   // false
undefined              // false
NaN                    // false

// всё остальное — truthy:
"false"                // true   (строка, не пустая)
"0"                    // true   (всё ещё строка)
[]                     // true   (пустой массив — объект, не пустота)
{}                     // true   (пустой объект)
function() {}          // true   (функция)
Infinity, -Infinity    // true

Самые контринтуитивные пункты — строки "false" и "0" (truthy) и пустые коллекции [], {} (тоже truthy, потому что это объекты). Из-за них прямой Boolean(x) не работает там, где значение пришло строкой из localStorage или URL.

!! — идиома короткого приведения

Стандартный способ превратить значение в булевое — Boolean(x). Но в коде гораздо чаще встречается короткая запись !!x — двойное логическое НЕ.

let user = { name: 'Сергей' };

// длинная запись
let hasUser = Boolean(user);    // true

// короткая
let hasUser2 = !!user;          // true

// внутри — два инвертирования: !user → false, !false → true
// если user = null: !null → true, !true → false

Оба варианта дают тот же результат. Boolean(x) предпочитают, когда читабельность важнее краткости (особенно в публичных функциях). !!x — в плотном коде, где привычка глаза уже сформирована. В TypeScript оба работают одинаково.

Подводные камни

Boolean("false") === true. Самая известная ловушка: любая непустая строка — truthy. Если из URL пришло ?active=false или из localStorage достали "false", — прямое преобразование вернёт true. Правильный способ — явное сравнение: x === "true". Или нормализация через JSON.parse(x) (она поймёт и "false", и "null", и числа).

Числа в булеве. Любое число, кроме нуля и NaN, truthy. Boolean(-1), Boolean(0.0001), Boolean(Infinity) — все true. Это полезно для проверок вида if (arr.length) — ноль элементов даст false, любое количество — true.

Boolean({}) и Boolean([]) всегда true. Объекты и массивы — не примитивы; для них логическое преобразование всегда даёт true. Если хочется «true только если есть что-то внутри», проверяй Object.keys(obj).length или arr.length.

Сравнение булевого через ==. true == 1true, true == "1" — тоже true, true == "true" — уже false (потому что строка "true" при сравнении с булевым превращается в число NaN). Чтобы избегать сюрпризов, используй строгое === или явно приводи оба значения к одному типу.

Объект-обёртка ведёт себя странно. new Boolean(false) — объект, а объект всегда truthy. Поэтому if (new Boolean(false)) попадает в if-ветку. Это одна из главных причин избегать конструктора без new — вызов Boolean(false) без new вернёт нормальное false.