Работа со строками в валидации часто упирается в проблему лишних пробелов: пользовательские вводы содержат ведущие и конечные пробелы, случайные двойные пробелы, табуляции или неочевидные символы Unicode. В схемах Yup это решается через встроенные трансформации строки и пользовательские преобразования, которые применяются до или во время валидации.
В Yup строковые схемы создаются через Yup.string(). Все
преобразования значения происходят на этапе трансформации, до выполнения
проверок required, min, max,
matches и других правил.
Ключевой момент: Yup сначала нормализует данные, затем валидирует их.
Это означает, что любое изменение строки, например удаление пробелов, влияет на итоговую проверку.
Основной инструмент для очистки строк — встроенный метод
.trim().
import * as Yup from 'yup';
const schema = Yup.object({
username: Yup.string()
.trim()
.required('Имя пользователя обязательно'),
});
Метод .trim() удаляет:
Пример преобразования:
" hello world " → "hello world"
"\n\tuser\t\n" → "user"
Важно, что внутренние пробелы не изменяются:
"john doe" → "john doe"
Одно из частых заблуждений связано с тем, как .trim()
влияет на required().
const schema = Yup.string()
.trim()
.required('Обязательное поле');
Если пользователь вводит:
" "
После .trim() строка становится:
""
И уже пустая строка считается невалидной для
required().
Таким образом, .trim() усиливает строгость проверки
обязательных полей, исключая случаи ввода “псевдозначений” из
пробелов.
Поведение изменяется при использовании nullable() и
notRequired().
const schema = Yup.string()
.trim()
.nullable()
.notRequired();
В этом случае:
null допустимundefined допустимВажно различать null и "", так как
.trim() не преобразует null.
Иногда требуется не только удалить пробелы по краям, но и нормализовать всю строку.
Yup позволяет использовать .transform():
const schema = Yup.string()
.transform((value) => {
if (typeof value !== 'string') return value;
return value.trim().replace(/\s+/g, ' ');
});
Здесь выполняется:
trim() — удаление внешних пробеловreplace(/\s+/g, ' ') — замена множественных пробелов
однимИногда требуется убрать все пробелы, включая внутренние.
const schema = Yup.string()
.transform((value) => {
if (typeof value !== 'string') return value;
return value.replace(/\s/g, '');
});
Результаты:
" a b c " → "abc"
"john doe" → "johndoe"
Такой подход используется редко, так как изменяет смысл строки, но полезен для идентификаторов, кодов или номеров.
Порядок методов в Yup имеет значение, поскольку трансформации выполняются до проверок.
Yup.string()
.trim()
.min(3);
или
Yup.string()
.min(3)
.trim();
Фактически корректным является первый вариант, поскольку:
.trim() должен очистить данные до проверки длиныminПример:
" abc "
Метод .trim() учитывает стандартные пробельные символы
Unicode:
\u00A0)Однако специфические символы пробела могут вести себя по-разному в зависимости от среды выполнения JavaScript.
На практике .trim() часто используется вместе с
ограничениями длины и формата:
const schema = Yup.string()
.trim()
.min(2)
.max(30)
.matches(/^[a-zA-Zа-яА-Я]+$/, 'Только буквы');
Здесь порядок критичен: сначала нормализация, затем проверки.
Yup.string().min(3)
Проблема: " a " проходит как длина 3, хотя фактическое
значение — один символ.
.transform(value => value.trim())
Ошибка возникает, если значение undefined или
null.
Корректный вариант:
.transform((value) => {
if (typeof value !== 'string') return value;
return value.trim();
});
Часто встречается ситуация, когда данные уже очищаются на уровне UI, а затем повторно через Yup. Это приводит к дублирующей обработке, которая не всегда очевидна при отладке.
Для большинства форм используется стандартная схема:
const cleanString = Yup.string()
.transform((value) => {
if (typeof value !== 'string') return value;
return value.trim().replace(/\s+/g, ' ');
})
.trim()
.required();
Такой подход обеспечивает:
При интеграции с формами (например, React Hook Form или Formik) важно учитывать, что Yup может изменять значение до отправки:
Это особенно важно для полей логинов, email и идентификаторов, где пробелы считаются критичными.
При использовании .oneOf() или .equals()
предварительная очистка может изменить результат сравнения:
Yup.string()
.trim()
.oneOf(['admin']);
В этом случае:
" admin " → "admin"
что приводит к успешному совпадению, даже если пользователь ввёл лишние пробелы.
Валидация строк в Yup строится на последовательной модели:
transform,
trim)min, max,
matches, required)Именно этап трансформации определяет, каким будет итоговое значение, поэтому работа с пробелами всегда должна рассматриваться как часть схемы, а не как внешний шаг обработки данных.