Метод when для условий

Метод when в Yup используется для построения условной схемы валидации, когда правила проверки зависят от значений других полей или текущего состояния данных. Это один из ключевых инструментов для создания динамических форм, где логика валидации не является статичной и меняется в зависимости от пользовательского ввода.

Валидация часто требует контекстности: поле может быть обязательным только при выполнении определённого условия, либо его ограничения меняются в зависимости от выбора пользователя. when позволяет декларативно описывать такие зависимости внутри схемы Yup без необходимости выносить логику валидации во внешний код.

Основная форма использования:

Yup.string().when('otherField', {
  is: value => value === 'something',
  then: schema => schema.required(),
  otherwise: schema => schema.notRequired()
});

Сигнатура и варианты использования

Вариант через объект условий

Наиболее читаемый и часто используемый формат:

when(key, options)

Где:

  • key — имя поля или массив полей, от которых зависит текущее правило

  • options — объект с условиями:

    • is — значение или функция-предикат
    • then — схема, применяемая при выполнении условия
    • otherwise — схема, применяемая в противном случае

Пример:

const schema = Yup.object({
  hasDiscount: Yup.boolean(),

  discountCode: Yup.string().when('hasDiscount', {
    is: true,
    then: schema => schema.required('Введите промокод'),
    otherwise: schema => schema.strip()
  })
});

Условие на основе значения другого поля

Один из самых распространённых сценариев — включение обязательности поля:

const schema = Yup.object({
  deliveryType: Yup.string().required(),

  address: Yup.string().when('deliveryType', {
    is: 'courier',
    then: schema => schema.required('Адрес обязателен при доставке курьером'),
    otherwise: schema => schema.notRequired()
  })
});

Здесь поле address становится обязательным только при выборе доставки курьером.

Использование функции в is

is может быть не только значением, но и функцией, что расширяет возможности проверки:

const schema = Yup.object({
  age: Yup.number(),

  guardianName: Yup.string().when('age', {
    is: value => value < 18,
    then: schema => schema.required('Для несовершеннолетних требуется опекун'),
    otherwise: schema => schema.notRequired()
  })
});

Функциональный подход удобен при сложных условиях сравнения.

Зависимость от нескольких полей

when поддерживает массив зависимостей:

const schema = Yup.object({
  country: Yup.string(),
  city: Yup.string(),

  postalCode: Yup.string().when(['country', 'city'], {
    is: (country, city) => country === 'KZ' && city === 'Karaganda',
    then: schema => schema.required(),
    otherwise: schema => schema.notRequired()
  })
});

Это позволяет учитывать контекст сразу нескольких значений.

Альтернативный синтаксис через функцию

Второй вариант when использует функцию-колбэк, возвращающую схему:

Yup.string().when('field', (fieldValue, schema) => {
  if (fieldValue === 'yes') {
    return schema.required('Обязательное поле');
  }
  return schema;
});

Этот подход полезен, когда логика более гибкая и не укладывается в структуру is/then/otherwise.

Условная валидация чисел

Пример с числовыми ограничениями:

const schema = Yup.object({
  hasLimit: Yup.boolean(),

  limit: Yup.number().when('hasLimit', {
    is: true,
    then: schema => schema.min(1).max(100).required(),
    otherwise: schema => schema.notRequired()
  })
});

Здесь диапазон значений применяется только при включённом флаге.

Работа со строками и форматами

Условные проверки часто используются для изменения формата данных:

const schema = Yup.object({
  type: Yup.string(),

  value: Yup.string().when('type', {
    is: 'email',
    then: schema => schema.email('Некорректный email').required(),
    otherwise: schema => schema.min(5)
  })
});

Фактически одно поле может менять свою семантику в зависимости от контекста.

Условие для вложенных объектов

when корректно работает внутри вложенных структур:

const schema = Yup.object({
  user: Yup.object({
    role: Yup.string(),
    permissions: Yup.string().when('role', {
      is: 'admin',
      then: schema => schema.required(),
      otherwise: schema => schema.notRequired()
    })
  })
});

Важно учитывать, что путь role может относиться к тому же объекту или быть внешним, в зависимости от структуры схемы.

Использование с массивами

В массивах when часто применяется для условий на элементы:

const schema = Yup.object({
  items: Yup.array().of(
    Yup.object({
      type: Yup.string(),

      value: Yup.string().when('type', {
        is: 'text',
        then: schema => schema.required(),
        otherwise: schema => schema.notRequired()
      })
    })
  )
});

Каждый элемент массива может иметь собственную условную логику.

Комбинация с test

when и test часто используются вместе. when задаёт условие применения схемы, а test — кастомную проверку:

const schema = Yup.object({
  password: Yup.string(),

  confirmPassword: Yup.string()
    .when('password', {
      is: value => !!value,
      then: schema => schema.required()
    })
    .test('match', 'Пароли не совпадают', function (value) {
      return value === this.parent.password;
    })
});

Такой подход позволяет разделять условие обязательности и логическую проверку.

Обработка сложных зависимостей

При сложных сценариях лучше комбинировать несколько when:

const schema = Yup.object({
  plan: Yup.string(),
  users: Yup.number(),

  price: Yup.number()
    .when('plan', {
      is: 'pro',
      then: schema => schema.min(100)
    })
    .when('users', {
      is: value => value > 10,
      then: schema => schema.min(200)
    })
});

Каждое условие накладывает дополнительное ограничение.

Поведение strip и трансформаций

when может использоваться для удаления поля из результата:

const schema = Yup.object({
  isVisible: Yup.boolean(),

  secret: Yup.string().when('isVisible', {
    is: false,
    then: schema => schema.strip(),
    otherwise: schema => schema
  })
});

strip() полностью исключает поле из валидированного объекта.

Частые ошибки при использовании

Неправильная ссылка на поле приводит к неработающей логике:

// ошибка: неправильное имя поля
Yup.string().when('wrongField', ...)

Также важно учитывать, что when зависит от текущего состояния объекта, и при асинхронном изменении формы может требоваться повторная валидация.

Некорректное использование функций в is без учёта типов часто приводит к неожиданным результатам:

is: value => value == 1 // нежелательное нестрогое сравнение

Особенности поведения внутри схемы Yup

  • when вычисляется во время валидации
  • зависимости берутся из текущего объекта данных
  • порядок объявления может влиять на читаемость, но не на результат
  • вложенные when выполняются независимо на каждом уровне схемы

Практические сценарии применения

  • динамические формы регистрации
  • настройки тарифных планов
  • условные адресные формы
  • многошаговые анкеты
  • конфигурационные интерфейсы
  • формы с переключаемыми режимами ввода

when становится центральным механизмом, когда форма перестаёт быть фиксированной и превращается в набор правил, зависящих от состояния данных.