Приведение типов
Вопрос
Почему [] + [] и [] == ![] ведут себя так странно, и когда приведение вообще уместно?
Короткий ответ
== приводит операнды к одному типу. === тип не приводит: разные типы дают false, кроме NaN, который не равен даже себе.
Сложение: если хотя бы один операнд строка, второй приводят к строке и конкатенируют. Иначе оба приводят к числу. У массива toString склеивает элементы через запятую, поэтому [] + [] это '', а [1] + [2] это '1,2'.
![] это false, потому что массив — объект и в логическом контексте истинен. Дальше [] == false приводит обе стороны к числу, 0 == 0, результат true.
Falsy-значения: false, 0, -0, 0n, '', null, undefined, NaN. Пустой массив и пустой объект истинны.
Разбор
Number('') === 0, Number(null) === 0, Number(undefined) это NaN. Поэтому null == undefined истинно по особому правилу, но null == 0 ложно: null не приводится к нулю в этом сравнении так, как ''.
Явные преобразования читаются лучше: Number(value), String(value), Boolean(value). В интерфейсе значение из инпута почти всегда строка, даже если пользователь ввёл цифры.
Object.is отличает -0 и +0 и считает NaN равным NaN. Обычное === для NaN не подходит, для проверки числа берут Number.isNaN. Глобальный isNaN сначала приводит аргумент и из-за этого путает строки.
На что смотрят на senior
На границе с API договариваются о контракте: нет значения — это null или отсутствие поля, а не пустая строка и не 0 вперемешку. Смешение заставляет каждый экран заново вспоминать таблицу приведения.
В TypeScript unknown заставляет сделать проверку до использования. Это как раз способ не полагаться на скрытое приведение в проде.
Типичные ошибки
- Писать
==«для удобства» и ловить0 == ''. - Проверять массив через
if (list), когда пустой список тоже надо отрисовать как валидное состояние. Пустой массив истинен, так что проверка на существование проходит, но длина всё равно нужна отдельно, если важен именно пустой UI. - Путать
typeof null === 'object'с настоящей проверкой объекта. Для объекта смотрятvalue !== null && typeof value === 'object'.
Задача
Какие сравнения истинны?
Boolean([])
0 == ''
null == undefined
null === undefinedПоказать ответ
Boolean([]) — true. Пустой массив объект, он истинен. Пустоту проверяют длиной.
0 == '' — true: оба приводятся к числу 0.
null == undefined — true по особому правилу ==. null === undefined — false, типы разные.