Смешанный тип в системе схем Yup представляет собой универсальный
контейнер для значений, которые не вписываются в строгую типизацию
строк, чисел, массивов или объектов. Он используется в ситуациях, когда
форма данных может изменяться в процессе работы приложения или когда
структура заранее не определена. В экосистеме Yup именно
mixed() становится базовой точкой расширения для построения
гибких и условных валидаторов, а при использовании вместе с YupResolver
он позволяет интегрировать динамические схемы в формы React Hook Form
без потери контроля над проверками.
Внутренне mixed в Yup — это абстрактный тип, который не
накладывает ограничений на структуру значения до тех пор, пока они явно
не определены разработчиком. Это означает, что любое значение проходит
первичную стадию принятия, а затем подвергается цепочке пользовательских
правил.
Ключевая особенность заключается в том, что mixed:
.test().transform().when()lazy()Эта модель делает его фундаментом для построения адаптивных схем, где тип данных может зависеть от внешних условий.
Создание схемы начинается с объявления универсального типа:
import * as yup from "yup";
const schema = yup.mixed();
На этом уровне схема допускает любое значение: строку, число, объект,
null, undefined, массив или даже экземпляры
классов. Однако реальная сила проявляется при добавлении
ограничений.
Несмотря на универсальность, mixed позволяет фиксировать
допустимые типы данных через явные проверки:
const schema = yup.mixed().oneOf([true, false]);
Такой подход используется для ограниченного множества значений, например флагов или перечислений нестандартной структуры.
Другой вариант — проверка типа вручную:
const schema = yup.mixed().test(
"is-string-or-number",
"Недопустимый тип",
(value) => typeof value === "string" || typeof value === "number"
);
mixed активно применяется для нормализации входных
данных. Особенно это важно при работе с формами, где пользовательский
ввод может приходить в разных форматах.
const schema = yup.mixed().transform((value) => {
if (value === "") return null;
return value;
});
Трансформация выполняется до этапа валидации, что позволяет приводить данные к предсказуемому виду.
Одним из наиболее характерных сценариев использования является обработка полей, структура которых заранее неизвестна. Например, динамические формы, где поля добавляются пользователем.
const schema = yup.object({
config: yup.mixed().test(
"is-valid-config",
"Некорректная конфигурация",
(value) => typeof value === "object" && value !== null
)
});
Такой подход позволяет оставить пространство для расширяемых структур, сохраняя контроль на уровне бизнес-логики.
Смешанный тип часто становится точкой входа для условных схем, где структура данных зависит от других значений формы.
const schema = yup.object({
type: yup.string(),
payload: yup.mixed().when("type", {
is: "file",
then: (schema) =>
schema.test("is-file", "Ожидается файл", (value) => value instanceof File),
otherwise: (schema) =>
schema.test("is-string", "Ожидается строка", (value) => typeof value === "string")
})
});
В такой конфигурации mixed выступает как переключатель
логики, делегируя проверку контексту.
Функция lazy() расширяет возможности mixed,
позволяя строить схему на основе значения в момент валидации:
const schema = yup.lazy((value) => {
if (Array.isArray(value)) {
return yup.array();
}
return yup.object();
});
Подобная конструкция часто используется для обработки структур с переменной вложенностью.
При использовании YupResolver в связке с React Hook Form смешанные типы требуют особого внимания, поскольку типизация формы может становиться менее строгой.
import { useForm } from "react-hook-form";
import { yupResolver } from "@hookform/resolvers/yup";
const { register, handleSubmit } = useForm({
resolver: yupResolver(schema)
});
В момент разрешения схемы mixed-поля возвращаются без
жёсткой типовой гарантии, что требует дополнительной обработки на уровне
приложения. Особенно это проявляется в TypeScript, где результат
валидации может быть расширен до unknown.
Одним из частых сценариев применения mixed является
работа с файлами, так как они не укладываются в стандартные примитивные
типы.
const schema = yup.object({
avatar: yup.mixed().test(
"fileSize",
"Файл слишком большой",
(value) => value && value.size <= 2000000
)
});
Здесь mixed становится контейнером для File
или Blob, а логика проверки полностью определяется
вручную.
Смешанный тип активно используется в системах, где одна и та же сущность может иметь разные формы представления.
const schema = yup.mixed().test(
"is-valid-shape",
"Неверная структура",
(value) =>
(value && typeof value === "string") ||
(value && typeof value === "object" && "id" in value)
);
Такая модель характерна для API-ответов, где данные могут приходить в разных форматах в зависимости от состояния системы.
В TypeScript mixed часто приводит к ослаблению строгой
типизации, так как итоговый тип становится неопределённым. Для
компенсации этого эффекта используются явные приведения и уточняющие
схемы.
const schema: yup.MixedSchema<string | number> = yup.mixed();
Однако при использовании YupResolver итоговый тип результата часто требует дополнительного сужения через пользовательские функции проверки.
Допускается использование mixed внутри сложных объектов,
где отдельные поля имеют динамическую природу.
const schema = yup.object({
metadata: yup.mixed(),
data: yup.object({
payload: yup.mixed(),
timestamp: yup.number()
})
});
Такая структура характерна для систем логирования, телеметрии и универсальных API-обёрток.
При всей гибкости mixed имеет ряд особенностей:
Эти свойства делают его инструментом не базового уровня, а расширенного контроля над схемами, где стандартные типы оказываются недостаточными.