Avatar ·

Как в TypeScript одновременно проверить и null, и undefined?

Привет, коллеги! Я новичок в TypeScript и столкнулся с проблемой, которая кажется простой, но вызывает путаницу. Мне нужно написать проверку, которая отсеивает как `null`, так и `undefined`. В JavaScript я привык просто писать `if (value)`, но в TypeScript это не всегда корректно, так как пустая строка или 0 тоже считаются falsy-значениями, и я могу потерять данные. Вот пример моего кода: ```typescript function processUser(user: { name: string | null | undefined; age?: number }) { // Как правильно проверить, что user.name не null и не undefined? if (user.name) { console.log(user.name.toUpperCase()); // Работает, но что если name = ""? } // Пробовал так: if (user.name !== null && user.name !== undefined) { console.log(user.name.length); // Работает, но код получается громоздким } } ``` Есть ли в TypeScript какой-то короткий и надёжный способ проверить одновременно на `null` и `undefined` без лишних условий? Может быть, есть оператор или функция, которые это делают за меня? Заранее спасибо за помощь! <<>>

Используйте строгую проверку с оператором != null

В TypeScript (и JavaScript) есть элегантный способ проверить сразу и null, и undefined — использовать оператор нестрогого неравенства != null. Это работает благодаря особенностям приведения типов в JavaScript: null == undefined возвращает true, поэтому value != null автоматически исключает оба значения.

function processUser(user: { name: string | null | undefined; age?: number }) {
  if (user.name != null) { // Проверяет и null, и undefined
    console.log(user.name.toUpperCase()); // TypeScript знает, что name — string
    console.log(user.name.length); // Безопасно
  }
}

TypeScript достаточно умён, чтобы понять эту проверку и выполнить сужение типа (type narrowing). После if (user.name != null) внутри блока user.name будет иметь тип string, а не string | null | undefined. Это одно из самых популярных решений в сообществе.

Важные нюансы

  • Не путайте с !== null — строгое неравенство !== не отсекает undefined. Всегда используйте != null (с одним знаком равенства).
  • Это работает только для null и undefined — другие falsy-значения (0, пустая строка, false) не будут отсеяны. Если вам нужно проверить, что значение существует и не является пустым, используйте дополнительную проверку.
  • Совместимость с optional chaining — можно комбинировать с оператором ?.:
// Безопасный доступ к вложенным свойствам
if (user.address?.city != null) {
  console.log(user.address.city); // city — точно string
}

Альтернативные подходы (когда они нужны)

Иногда вам может потребоваться явно различать null и undefined (например, в API-ответах). В таких случаях используйте строгую проверку:

if (value === null) {
  // Только null
}
if (value === undefined) {
  // Только undefined
}

Но для 90% случаев != null — это самое чистое и идиоматичное решение. Оно короткое, понятное и полностью поддерживается системой типов TypeScript. Многие опытные разработчики используют именно его, чтобы избежать многословных конструкций вида value !== null && value !== undefined.

Рекомендация: Включите в tsconfig.json правило strictNullChecks: true — это заставит TypeScript строго следить за null/undefined и сделает код безопаснее.

<<>>

Использование оператора ?? (nullish coalescing) для значений по умолчанию

Если ваша задача — не просто проверить, а подставить значение по умолчанию, когда переменная null или undefined, используйте оператор nullish coalescing ??. Он возвращает правый операнд только если левый — null или undefined (в отличие от ||, который реагирует на любые falsy-значения).

const userName = user.name ?? "Гость"; // Если name null/undefined — "Гость"
// Если name = "" или 0 — вернётся пустая строка/0 (корректно!)

// Комбинация с проверкой:
const displayName = user.name ?? "Не указано";
if (displayName !== "Не указано") {
  console.log(displayName.toUpperCase());
}

Этот подход особенно полезен при работе с формами, API-ответами или конфигурациями, где нужно сохранить пустую строку или ноль как валидные значения, но подставить дефолт только при полном отсутствии данных.

Недостаток: ?? не выполняет сужение типа в TypeScript — переменная остаётся исходного типа (например, string | null). Для сужения типа всё равно потребуется if (value != null).

// Сужение типа не произойдёт:
const x = value ?? "default";
// x всё ещё может быть null, если value был null? Нет, x — это string.
// Но сам value остаётся string | null.