Булевы значения

Логическая модель boolean-типа в схемах Yup

Булев тип в схемах валидации используется для представления строго бинарных значений: true и false. В контексте Yup он реализуется через yup.boolean(), который расширяет базовый тип mixed и добавляет поведение приведения типов (casting), проверки и комбинирования с условиями.

Ключевая особенность boolean в Yup заключается в том, что входные данные редко приходят в строго логическом виде. Формы HTML, API-ответы и пользовательский ввод часто передают строки ("true", "false"), числа (0, 1) или даже неопределённые значения. Поэтому механизм кастинга становится центральной частью работы схемы.

import * as yup from "yup";

const schema = yup.object({
  isActive: yup.boolean()
});

Приведение типов (casting) boolean значений

В Yup реализована встроенная нормализация входных данных. При работе с boolean происходит преобразование значения перед валидацией.

Основные правила кастинга:

  • "true"true
  • "false"false
  • truetrue
  • falsefalse
  • 1true
  • 0false
  • пустые значения → false (в зависимости от контекста и nullable)

Особенность заключается в том, что строка "false" не является ложной в JavaScript, но в Yup она корректно интерпретируется как логическое false.

yup.boolean().cast("true");  // true
yup.boolean().cast("false"); // false
yup.boolean().cast(1);       // true
yup.boolean().cast(0);       // false

Такой подход устраняет типовые ошибки при работе с формами, где значения приходят как строки.


Поведение с HTML checkbox

В DOM checkbox возвращает значение через event.target.checked, которое уже является boolean. Однако при использовании библиотек форм, например react-hook-form, промежуточные значения могут становиться строками.

Типичная модель данных:

<input type="checkbox" name="agree" />
{
  agree: true
}

При интеграции с resolver слой Yup получает значение и применяет кастинг:

const schema = yup.object({
  agree: yup.boolean().oneOf([true], "Необходимо согласие")
});

Обязательные boolean-значения

По умолчанию boolean в Yup допускает undefined, если не указан .required(). Однако .required() не всегда означает обязательное значение true.

yup.boolean().required();

Такое правило проверяет лишь наличие значения, но не его логическое содержание.

Различие:

  • required() — значение должно существовать
  • oneOf([true]) — значение должно быть строго true

Ограничение значений через oneOf

Наиболее частый сценарий использования boolean — подтверждение действий (согласие, подтверждение, принятие условий).

const schema = yup.object({
  termsAccepted: yup.boolean().oneOf([true], "Необходимо принять условия")
});

Здесь допустимым значением является только true. Значение false или отсутствие значения приведёт к ошибке валидации.


Nullable boolean и неопределённые состояния

В некоторых моделях данных требуется три состояния:

  • true
  • false
  • null

Для этого используется .nullable():

const schema = yup.object({
  isVerified: yup.boolean().nullable()
});

Такой подход применяется в случаях, когда состояние ещё не определено (например, асинхронная проверка или отсутствие ответа API).


Значения по умолчанию

Boolean поля часто требуют явного начального состояния. В Yup это реализуется через .default().

const schema = yup.object({
  isActive: yup.boolean().default(false)
});

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


Комбинирование с transform

Метод .transform() позволяет вручную управлять логикой преобразования входного значения. Это полезно при нестандартных источниках данных.

const schema = yup.object({
  flag: yup.boolean().transform((value, originalValue) => {
    if (originalValue === "yes") return true;
    if (originalValue === "no") return false;
    return value;
  })
});

Transform выполняется до основной проверки типа, что позволяет адаптировать схему под внешние API.


Условная логика (when) для boolean

Boolean-значения часто используются как триггеры для включения или отключения других полей схемы.

const schema = yup.object({
  hasDiscount: yup.boolean(),
  discountCode: yup.string().when("hasDiscount", {
    is: true,
    then: (schema) => schema.required(),
    otherwise: (schema) => schema.notRequired()
  })
});

Такая конструкция формирует зависимую структуру данных, где boolean управляет валидностью других полей.


Интеграция с YupResolver

В связке с react-hook-form используется yupResolver, который связывает Yup-схему с системой валидации формы.

import { useForm } from "react-hook-form";
import { yupResolver } from "@hookform/resolvers/yup";

const schema = yup.object({
  isActive: yup.boolean().oneOf([true])
});

const form = useForm({
  resolver: yupResolver(schema),
  defaultValues: {
    isActive: false
  }
});

Процесс обработки:

  1. Пользователь изменяет состояние формы
  2. Значения попадают в resolver
  3. Yup выполняет кастинг boolean
  4. Срабатывает валидация схемы
  5. Возвращаются ошибки (если есть)
  6. react-hook-form обновляет состояние errors

Особенности работы с типизацией TypeScript

При использовании TypeScript Yup может выводить тип boolean через InferType.

import * as yup from "yup";

const schema = yup.object({
  isActive: yup.boolean()
});

type FormData = yup.InferType<typeof schema>;

Результирующий тип:

type FormData = {
  isActive?: boolean | undefined;
};

При использовании .required() и .default() тип может становиться более строгим:

const schema = yup.object({
  isActive: yup.boolean().required().default(false)
});

Сравнение boolean с другими типами в Yup

Boolean в Yup отличается от string и number тем, что:

  • имеет встроенную логику кастинга
  • поддерживает семантические преобразования ("true", "false")
  • чаще используется как управляющий флаг
  • активно участвует в conditional validation

В отличие от строк и чисел, boolean не требует сложной нормализации входных данных при стандартных сценариях форм.


Частые ошибки при работе с boolean

Одной из распространённых проблем является ожидание поведения JavaScript при приведении типов:

Boolean("false") // true

Однако в Yup:

yup.boolean().cast("false") // false

Ещё один типичный сценарий — отсутствие .oneOf([true]) при работе с чекбоксами согласия. В результате форма считается валидной даже при false.


Поведение undefined и initial state

При отсутствии значения поле boolean может находиться в состоянии undefined. Это влияет на:

  • отображение ошибок
  • работу defaultValues
  • результат кастинга

Рекомендуемая модель данных для форм:

  • явное default(false)
  • использование .oneOf([true]) для обязательных согласий
  • избегание неявного undefined в критичных флагах

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

Boolean активно применяется как управляющий элемент в больших схемах:

const schema = yup.object({
  isCompany: yup.boolean(),
  companyName: yup.string().when("isCompany", {
    is: true,
    then: (s) => s.required(),
    otherwise: (s) => s.strip()
  }),
  hasAddress: yup.boolean(),
  address: yup.object().when("hasAddress", {
    is: true,
    then: (s) => s.required(),
    otherwise: (s) => s.nullable()
  })
});

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