Иногда создание объекта — это сложный и даже многоэтапный процесс с дополнительными условиями. К таким объектам относятся валидаторы, реализованные в объектном стиле.
Валидация — это процесс проверки данных на корректность по заданным условиям. А валидатор — это что-то, выполняющее данную проверку.
В программировании валидация встречается на каждом шагу. Мы так или иначе работаем с формами или данными, отправляемыми по API. Все эти данные присылаются пользователями или внешними системами и автоматически считаются недоверенными. Перед тем как работать с ними, сначала нужно убедиться что они "валидные", то есть соответствуют нашим требованиям. Например, если мы говорим про емейл пользователя, то для большинства форм регистрации он должен быть не пустой и должен соответствовать формату емейлов.
Самый простой способ сделать валидацию, это выполнить ручную проверку:
if (data.email === '') {
errors.push('емейл пустой');
}
// гипотетическая функция проверки формата
if (!hasEmailFormat(data.email)) {
errors.push('емейл имеет неверный формат');
}
Нетрудно представить, как разрастется этот код для большой формы со множеством правил. У такого способа есть и другие проблемы. Он не позволяет легко переиспользовать правила для разных форм и проектов. Кроме того, многие проверки придется либо реализовывать самостоятельно, либо искать готовые библиотеки для них. Например, для проверки корректности ссылок, адресов и других вещей.
Yup
В JavaScript для выполнения валидации очень популярна библиотека yup. Посмотрите на пример, эквивалентный проверкам выше:
import * as yup from 'yup';
const schema = yup.string().required().email();
schema.validateSync(''); // ValidationError: this is a required field
schema.validateSync('wrongemail'); // ValidationError: this must be a valid email
schema.validateSync('support@hexlet.io'); // возвращает само значение
Принцип работы этой библиотеки следующий. С помощью цепочки методов формируется схема валидации. В эту цепочку входят различные условия, которые должны выполняться по принципу объединения. То есть для успешной валидации должны выполниться все условия. Сами условия зависят от того, какого типа проверяемые данные, поэтому в начале вызывается метод, задающий тип, и затем вызываются методы, которые относятся к данному типу данных:
// методы positive() и integer() есть только у number
const schema1 = yup.number().required().positive().integer();
// массив должен содержать от 5 до 10 элементов
const schema2 = yup.array().min(5).max(10);
Во всех этих ситуациях наша задача – сформировать правильную схему под конкретную задачу. Затем эту схему можно использовать множество раз на разных данных. Подобный способ формирования объекта-схемы называется сборкой, а сам объект – сборщиком. По большому счету это небольшая разновидность использования текучего интерфейса. Чем он удобен? С его помощью просто собирать даже сложные проверки, используя очень понятную механику объединения вызовов. Код при этом получается простым и понятным.
Из дополнительных плюсов – наличие готовых сообщений об ошибках для всех встроенных проверок. При необходимости их можно поменять для конкретной схемы, просто передав текст в методы проверок:
// Замена идет только для данной схемы
const schema1 = yup.string().required('Пусто!');
const schema2 = yup.string().required(); // здесь будет значение по умолчанию
Yup поддерживает не только разные тексты, но и разные локали, что актуально для многоязычных сайтов.
А что делать в ситуации, когда мы работаем с объектом, у которого каждое свойство имеет свои собственные проверки? Yup решает эту задачу очень элегантно, через рекурсивное определение:
// object().shape() позволяет задать структуру объекта
const schema = yup.object().shape({
name: yup.string().required(),
age: yup.number().required().positive().integer(),
email: yup.string().email(),
website: yup.string().url(),
createdOn: yup.date().default(() => new Date()), // значение по умолчанию
});
const data = {
name: 'jimmy',
age: 24,
};
schema.validateSync(data);
https://repl.it/@hexlet/js-object-oriented-design-buider-yup-object#index.js
Но и это еще не все, yup позволяет добавлять дополнительные проверки, которые изначально в него не включены. Подробнее про эту возможность можно прочитать в документации.
Дополнительные материалы
Остались вопросы? Задайте их в разделе «Обсуждение»
Вам ответят команда поддержки Хекслета или другие студенты
Для полного доступа к курсу нужен базовый план
Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.