Библиотека Yup поддерживает механизм преобразования значений до этапа проверки. Это один из важнейших аспектов работы схем, поскольку входящие данные редко приходят в идеально подготовленном виде. Пользовательские формы, HTTP-запросы, query-параметры, данные из CSV и JSON часто содержат строки вместо чисел, пробелы, пустые значения или нестандартные форматы.
Преобразование выполняется автоматически перед запуском валидаторов. Благодаря этому схема может не только проверять данные, но и нормализовывать их.
Основной инструмент преобразования — метод
transform().
Сигнатура:
schema.transform((currentValue, originalValue) => {
return transformedValue;
});
Аргументы:
currentValue — текущее значение после предыдущих
преобразованийoriginalValue — исходное значение до любых
трансформацийПример:
import * as yup from 'yup';
const schema = yup.string().transform((value) => {
return value.trim();
});
schema.cast(' hello ');
// "hello"
Метод cast() показывает результат преобразования без
запуска валидации.
Внутри Yup обработка происходит в следующем порядке:
transform()required, min,
matches и др.)Пример:
const schema = yup
.string()
.transform((value) => value.trim())
.min(3);
await schema.validate(' abc ');
Этапы:
" abc "
↓
"abc"
↓
min(3)
↓
успешная проверка
Yup никогда не мутирует оригинальные данные.
const user = {
name: ' Alex '
};
const schema = yup.object({
name: yup.string().transform(v => v.trim())
});
const result = schema.cast(user);
console.log(user.name);
// " Alex "
console.log(result.name);
// "Alex"
Только преобразует данные.
schema.cast(value);
Преобразует и валидирует.
await schema.validate(value);
Пример:
const schema = yup.number();
schema.cast('42');
// 42
await schema.validate('42');
// 42
Yup умеет автоматически преобразовывать типы.
const schema = yup.number();
schema.cast('100');
// 100
const schema = yup.boolean();
schema.cast('true');
// true
const schema = yup.date();
schema.cast('2025-01-01');
По умолчанию Yup приводит типы автоматически. Метод
strict() отключает это поведение.
const schema = yup.number().strict();
await schema.validate('42');
Ошибка:
this must be a `number` type
Без strict() строка была бы преобразована в число.
Удаляет пробелы по краям.
const schema = yup.string().trim();
schema.cast(' hello ');
// "hello"
Преобразует строку в нижний регистр.
const schema = yup.string().lowercase();
schema.cast('HELLO');
// "hello"
const schema = yup.string().uppercase();
schema.cast('hello');
// "HELLO"
Трансформации можно объединять.
const schema = yup
.string()
.trim()
.lowercase()
.transform(v => v.replace(/\s+/g, '-'));
schema.cast(' HELLO WORLD ');
// "hello-world"
Очень распространённая задача — преобразование пустой строки в
null.
const schema = yup
.string()
.nullable()
.transform((value) => {
return value === '' ? null : value;
});
schema.cast('');
// null
Особенно полезно для HTML-форм.
Метод nullable() разрешает null как
валидное значение.
const schema = yup
.number()
.nullable();
Без nullable() значение null вызовет
ошибку.
const schema = yup.number().transform((value, originalValue) => {
if (typeof originalValue === 'string') {
return Number(originalValue.replace(/\s/g, ''));
}
return value;
});
schema.cast('1 000');
// 1000
const schema = yup.number().transform((value, originalValue) => {
return Number(
originalValue
.replace('$', '')
.replace(',', '')
);
});
schema.cast('$1,500');
// 1500
originalValue особенно важен, когда Yup уже выполнил
автоматическое преобразование.
Пример:
const schema = yup.number().transform((value, originalValue) => {
console.log(value);
console.log(originalValue);
return value;
});
Для строки "42":
value = 42
originalValue = "42"
const schema = yup.date().transform((value, originalValue) => {
const parts = originalValue.split('.');
return new Date(
parts[2],
parts[1] - 1,
parts[0]
);
});
schema.cast('25.12.2025');
const schema = yup.date().transform((value, originalValue) => {
const date = new Date(originalValue);
return isNaN(date.getTime())
? null
: date;
});
const schema = yup.array().of(
yup.string().trim().lowercase()
);
schema.cast([
' JS ',
' NODE '
]);
// ["js", "node"]
const schema = yup.array().transform((value, originalValue) => {
if (typeof originalValue === 'string') {
return originalValue.split(',');
}
return value;
});
schema.cast('a,b,c');
// ["a", "b", "c"]
const schema = yup.object({
name: yup.string().trim(),
email: yup.string().lowercase().trim()
});
schema.cast({
name: ' Alex ',
email: ' TEST@MAIL.COM '
});
Результат:
{
name: 'Alex',
email: 'test@mail.com'
}
Метод удаляет поля, которых нет в схеме.
const schema = yup.object({
name: yup.string()
});
schema.cast(
{
name: 'Alex',
role: 'admin'
},
{
stripUnknown: true
}
);
Результат:
{
name: 'Alex'
}
const schema = yup.string().default('Anonymous');
schema.cast(undefined);
// "Anonymous"
transform() выполняется раньше
default().
const schema = yup
.string()
.transform(v => v === '' ? undefined : v)
.default('Empty');
schema.cast('');
// "Empty"
Пример подготовки формы регистрации:
const schema = yup.object({
name: yup
.string()
.trim(),
email: yup
.string()
.trim()
.lowercase(),
age: yup
.number()
.transform((value, originalValue) => {
return originalValue === ''
? null
: value;
})
.nullable(),
tags: yup
.array()
.transform((value, originalValue) => {
if (typeof originalValue === 'string') {
return originalValue
.split(',')
.map(v => v.trim());
}
return value;
})
});
Входные данные:
{
name: ' Alex ',
email: ' TEST@MAIL.COM ',
age: '',
tags: 'js, node, react'
}
После cast():
{
name: 'Alex',
email: 'test@mail.com',
age: null,
tags: ['js', 'node', 'react']
}
Трансформации всегда синхронные.
Нельзя:
.transform(async value => {
return await fetchSomething(value);
})
transform() должен возвращать значение сразу.
Если схема работает в strict-режиме:
const schema = yup
.string()
.strict();
Некоторые встроенные преобразования отключаются, но пользовательские
transform() продолжают работать.
Метод проверяет, соответствует ли значение типу схемы.
const schema = yup.number();
schema.isType(42);
// true
schema.isType('42');
// false
Полезно внутри трансформаций:
const schema = yup.number().transform((value, originalValue) => {
if (schema.isType(value)) {
return value;
}
return Number(originalValue);
});
Преобразование числа может вернуть NaN.
const schema = yup.number();
schema.cast('abc');
// NaN
Без дополнительной обработки это приведёт к ошибке валидации.
Безопасный вариант:
const schema = yup.number().transform((value) => {
return isNaN(value)
? undefined
: value;
});
Внутри transform() доступен контекст схемы через
this.
const schema = yup.string().transform(function(value) {
console.log(this.path);
return value;
});
Важно использовать обычную функцию, а не стрелочную.
Трансформации выполняются последовательно.
const schema = yup
.string()
.transform(v => v.trim())
.transform(v => v.toUpperCase());
schema.cast(' hello ');
// "HELLO"
Трансформации вызываются при каждом:
cast()validate()validateSync()Сложные вычисления внутри transform() могут влиять на
производительность при обработке больших форм.
Нежелательно:
.transform(value => {
return expensiveOperation(value);
})
Практический сценарий:
const schema = yup.object({
username: yup
.string()
.trim()
.lowercase(),
phone: yup
.string()
.transform(v => v.replace(/\D/g, '')),
salary: yup
.number()
.transform((v, original) => {
return Number(
original.replace(/[^\d]/g, '')
);
})
});
Результат:
{
username: 'alex',
phone: '79991234567',
salary: 250000
}
.transform(value => {
value.trim();
})
Результат:
undefined
Правильно:
.transform(value => {
return value.trim();
})
.transform(value => value.trim())
При null возникнет ошибка.
Безопасный вариант:
.transform(value => {
return typeof value === 'string'
? value.trim()
: value;
})
Неправильно:
.transform(obj => {
obj.name = obj.name.trim();
return obj;
})
Лучше:
.transform(obj => ({
...obj,
name: obj.name.trim()
}))
const apiSchema = yup.object({
id: yup.number(),
status: yup
.string()
.trim()
.uppercase(),
active: yup.boolean(),
createdAt: yup.date(),
tags: yup.array().of(
yup.string().trim().lowercase()
)
});
Вход:
{
id: '15',
status: ' active ',
active: 'true',
createdAt: '2025-01-01',
tags: [' JS ', ' NODE ']
}
Результат:
{
id: 15,
status: 'ACTIVE',
active: true,
createdAt: Date,
tags: ['js', 'node']
}
В Yup трансформации выполняют несколько задач одновременно:
Благодаря этому схема становится не только инструментом проверки, но и полноценным уровнем предобработки данных.