Undefined и null значения

Базовая модель поведения undefined и null

Валидационная модель Yup строится вокруг строгого различения трёх состояний значения:

  • undefined — значение отсутствует
  • null — значение явно задано как пустое
  • фактическое значение (строка, число, объект и т.д.)

Эти состояния по умолчанию обрабатываются по-разному, и это напрямую влияет на результат валидации.

undefined в большинстве схем трактуется как отсутствие значения и часто активирует правила required(), если они заданы.

null рассматривается как явное значение и не эквивалентен отсутствию данных. Это ключевой момент, который влияет на поведение схем.


Поведение undefined валидации

Значение undefined в Yup почти всегда интерпретируется как «поле не заполнено».

Пример базового поведения:

import * as Yup from "yup";

const schema = Yup.string().required();

schema.validate(undefined);

Результат: ошибка валидации, так как required() требует наличия значения.

Особенности обработки:

  • undefined считается отсутствием значения
  • активирует required() при его наличии
  • может заменяться через default()
  • часто появляется при работе с формами (например, React Hook Form)

Поведение null

null в Yup является отдельным допустимым значением, которое не всегда считается отсутствием данных.

const schema = Yup.string().required();

schema.validate(null);

Результат: валидация может пройти или упасть в зависимости от конфигурации схемы.

Ключевые сценарии:

  • без nullable() null часто вызывает ошибку
  • с nullable(true) null становится допустимым значением
  • используется для явного «пустого состояния»

Метод nullable()

Метод nullable() управляет допустимостью null:

const schema = Yup.string().nullable();

schema.validate(null);

Теперь null считается валидным значением.

Важные особенности:

  • не влияет на undefined
  • не заменяет required()
  • делает null допустимым значением на уровне типа

Комбинация:

Yup.string().nullable().required();

означает: null допустим, но пустое значение (включая undefined) недопустимо.


Метод defined()

defined() в Yup используется для запрета undefined.

const schema = Yup.string().defined();

Поведение:

  • undefined → ошибка
  • null → допускается (если не запрещён отдельно)
  • используется для строгой схемы данных

Различие required() и defined()

Эти методы часто путаются, но их семантика различна:

required()

  • проверяет наличие «значимого» значения
  • часто блокирует undefined, null, пустые строки (в зависимости от типа)

defined()

  • проверяет исключительно отсутствие undefined
  • не заботится о «пустоте» значения

Поведение по умолчанию

Без дополнительных модификаторов поведение схемы в Yup можно описать так:

  • undefined → считается отсутствующим значением
  • null → может считаться невалидным (зависит от типа)
  • пустые значения часто требуют явного разрешения

Работа с default()

Метод default() позволяет заменять undefined:

const schema = Yup.string().default("значение по умолчанию");

schema.cast(undefined);

Результат: "значение по умолчанию"

Особенности:

  • применяется при cast()
  • не влияет на null
  • используется для нормализации входных данных

transform() и нормализация null / undefined

Метод transform() позволяет централизованно управлять поведением значений:

const schema = Yup.string().transform((value, originalValue) => {
  if (originalValue === null) return "";
  return value;
});

Типичные сценарии:

  • преобразование null в пустую строку
  • замена undefined на дефолтные значения
  • унификация входных данных из API или форм

Влияние типа схемы

Разные типы в Yup по-разному реагируют на null и undefined:

string()

  • undefined → отсутствие значения
  • null → требует nullable()

number()

  • null обычно невалиден без nullable()
  • undefined может активировать required()

object()

  • undefined → ошибка при required()
  • null часто требует явного разрешения

Комбинированные схемы и edge-case сценарии

В реальных схемах часто встречаются комбинации:

const schema = Yup.object({
  name: Yup.string().nullable().defined(),
});

Поведение:

  • undefined запрещён
  • null разрешён
  • строка валидируется как обычно

Влияние сериализации данных

При интеграции с API часто возникает различие:

  • JSON не поддерживает undefined
  • null передаётся явно

Это приводит к тому, что:

  • undefined появляется только на уровне приложения
  • null приходит с сервера как осознанное значение

В Yup это различие критично при валидации входных DTO.


Поведение при stripUnknown

При использовании:

Yup.object().noUnknown()

или аналогичных конфигураций:

  • undefined может быть удалён до валидации
  • null сохраняется как значение

Практическая модель различий

Поведение можно обобщить:

  • undefined — отсутствие данных на уровне структуры
  • null — намеренно пустое значение
  • Yup требует явного указания, как трактовать оба состояния

Типовые ошибки при работе с undefined и null

Ошибка 1: ожидание равенства null и undefined

В Yup это разные состояния и не взаимозаменяемы.

Ошибка 2: использование required() вместо defined()

required() не всегда покрывает сценарии строгой проверки структуры.

Ошибка 3: отсутствие nullable()

Приводит к неожиданным ошибкам при передаче null из API.


Стратегии проектирования схем

При проектировании схем в Yup обычно применяются следующие подходы:

  • использовать nullable() для API-данных с явными пустыми значениями
  • использовать defined() для строгих структур
  • использовать default() для нормализации отсутствующих значений
  • избегать неявной зависимости от undefined в бизнес-логике

Поведение в цепочках методов

Порядок вызова методов влияет на итоговую логику:

Yup.string().required().nullable();

и

Yup.string().nullable().required();

могут вести себя по-разному в зависимости от версии и контекста, так как обработка null и required() выполняется на разных этапах валидационного пайплайна.