Введение: что такое Valibot и зачем он нужен?
Valibot — это современная, модульная и лёгкая библиотека для валидации данных на языке TypeScript и JavaScript. В отличие от таких гигантов, как Zod или Joi, Valibot спроектирован с акцентом на минимальный размер бандла и tree-shaking (возможность удаления неиспользуемого кода).
Основная философия Valibot — «плати только за то, что используешь». Если вам нужно проверить только строку на минимальную длину, вы импортируете только string и minLength, а не всю библиотеку целиком. Это делает Valibot идеальным выбором для проектов, где важен размер итогового JavaScript-бандла (например, для мобильных приложений или библиотек компонентов).
Библиотека полностью типизирована и предоставляет отличную интеграцию с TypeScript, автоматически выводя типы из схем валидации. Valibot поддерживает как простые примитивы (строки, числа, булевы значения), так и сложные структуры (объекты, массивы, union-типы, рекурсивные схемы).
Установка
Valibot распространяется через пакетный менеджер npm. Для установки выполните следующую команду в терминале вашего проекта:
npm install valibot
Если вы используете yarn:
yarn add valibot
Для pnpm:
pnpm add valibot
После установки вы можете импортировать необходимые функции в ваш TypeScript-файл:
import { string, number, object, minLength, maxValue } from 'valibot';
Быстрый старт с примером кода
Давайте создадим простую схему валидации для формы регистрации пользователя. Мы проверим имя, email и возраст.
import { object, string, number, email, minLength, maxValue, safeParse } from 'valibot';
// 1. Определяем схему
const UserSchema = object({
name: string([minLength(2, 'Имя должно содержать минимум 2 символа')]),
email: string([email('Некорректный email')]),
age: number([maxValue(120, 'Возраст не может быть больше 120')])
});
// 2. Данные для проверки
const inputData = {
name: 'Анна',
email: 'anna@example.com',
age: 30
};
// 3. Валидируем
const result = safeParse(UserSchema, inputData);
if (result.success) {
console.log('Данные валидны:', result.output);
// result.output имеет тип { name: string; email: string; age: number; }
} else {
console.error('Ошибки валидации:', result.issues);
// result.issues — массив объектов с описанием ошибок
}
В этом примере мы использовали safeParse — безопасный метод, который не выбрасывает исключение, а возвращает объект с полем success. Если валидация прошла успешно, в result.output будут лежать проверенные данные с корректными типами.
Основные методы и функции
Valibot предоставляет множество функций для создания схем. Рассмотрим самые важные из них.
1. string()
Что делает: Создаёт схему для валидации строковых значений. Принимает необязательный массив валидаторов для дополнительных проверок (длина, паттерн и т.д.).
Параметры:
validations(необязательно): массив функций-валидаторов, таких какminLength,maxLength,email,url,regexи других.
Пример:
import { string, minLength, maxLength, email } from 'valibot';
const UsernameSchema = string([minLength(3), maxLength(20)]);
const EmailSchema = string([email()]);
console.log(safeParse(UsernameSchema, 'Jo')); // { success: false, issues: [...] }
console.log(safeParse(EmailSchema, 'test@test.com')); // { success: true, output: 'test@test.com' }
2. number()
Что делает: Создаёт схему для валидации числовых значений. Поддерживает целые числа и числа с плавающей точкой.
Параметры:
validations(необязательно): массив валидаторов, таких какminValue,maxValue,integer,positiveи других.
Пример:
import { number, minValue, maxValue, integer } from 'valibot';
const AgeSchema = number([integer(), minValue(0), maxValue(150)]);
const PriceSchema = number([minValue(0.01)]);
console.log(safeParse(AgeSchema, 25.5)); // { success: false } — не целое
console.log(safeParse(PriceSchema, 100)); // { success: true, output: 100 }
3. boolean()
Что делает: Создаёт схему для валидации булевых значений (true или false).
Параметры: Нет.
Пример:
import { boolean } from 'valibot';
const IsActiveSchema = boolean();
console.log(safeParse(IsActiveSchema, true)); // { success: true, output: true }
console.log(safeParse(IsActiveSchema, 'true')); // { success: false }
4. object()
Что делает: Создаёт схему для валидации объектов. Принимает объект, где ключи — это названия полей, а значения — схемы для этих полей.
Параметры:
entries: объект, определяющий структуру и типы полей.validations(необязательно): массив валидаторов для всего объекта (например, для проверки зависимостей между полями).
Пример:
import { object, string, number } from 'valibot';
const ProductSchema = object({
title: string(),
price: number()
});
const result = safeParse(ProductSchema, { title: 'Книга', price: 500 });
console.log(result.success); // true
5. array()
Что делает: Создаёт схему для валидации массивов. Принимает схему для элемента массива.
Параметры:
item: схема для каждого элемента массива.validations(необязательно): массив валидаторов для всего массива, напримерminLength,maxLength.
Пример:
import { array, string, minLength } from 'valibot';
const TagsSchema = array(string(), [minLength(1, 'Должен быть хотя бы один тег')]);
console.log(safeParse(TagsSchema, ['typescript', 'valibot'])); // { success: true }
console.log(safeParse(TagsSchema, [])); // { success: false }
6. union()
Что делает: Создаёт схему, которая принимает значение, соответствующее одной из переданных схем (логическое ИЛИ). Полезно для полей, которые могут быть разных типов.
Параметры:
options: массив схем, из которых нужно выбрать.
Пример:
import { union, string, number } from 'valibot';
const IdSchema = union([string(), number()]);
console.log(safeParse(IdSchema, 'abc123')); // { success: true, output: 'abc123' }
console.log(safeParse(IdSchema, 42)); // { success: true, output: 42 }
console.log(safeParse(IdSchema, true)); // { success: false }
7. optional()
Что делает: Делает схему опциональной. Если значение undefined или null, валидация проходит успешно, и возвращается undefined (или можно указать значение по умолчанию).
Параметры:
schema: схема, которую нужно сделать опциональной.defaultValue(необязательно): значение, которое будет использовано, если входное значение отсутствует.
Пример:
import { object, string, optional } from 'valibot';
const UserSchema = object({
name: string(),
nickname: optional(string(), 'Аноним')
});
const result1 = safeParse(UserSchema, { name: 'Иван' });
console.log(result1.output); // { name: 'Иван', nickname: 'Аноним' }
const result2 = safeParse(UserSchema, { name: 'Иван', nickname: 'Вано' });
console.log(result2.output); // { name: 'Иван', nickname: 'Вано' }
8. nullable()
Что делает: Позволяет значению быть null в дополнение к основному типу. Отличается от optional тем, что nullable разрешает null, но не undefined.
Параметры:
schema: схема, которую нужно расширить для поддержкиnull.
Пример:
import { string, nullable } from 'valibot';
const NicknameSchema = nullable(string());
console.log(safeParse(NicknameSchema, 'Петя')); // { success: true, output: 'Петя' }
console.log(safeParse(NicknameSchema, null)); // { success: true, output: null }
console.log(safeParse(NicknameSchema, undefined)); // { success: false }
9. pipe()
Что делает: Позволяет объединить несколько схем в одну, применяя их последовательно. Это мощный инструмент для трансформации данных (например, преобразование строки в число после валидации).
Параметры:
schemas: массив схем, которые будут применяться по порядку. Результат выполнения предыдущей схемы передаётся в следующую.
Пример:
import { pipe, string, transform, minLength } from 'valibot';
// Схема, которая принимает строку, проверяет длину и преобразует в число
const StringToNumberSchema = pipe(
string([minLength(1)]),
transform((input) => Number(input))
);
const result = safeParse(StringToNumberSchema, '123');
console.log(result); // { success: true, output: 123 (number) }
const result2 = safeParse(StringToNumberSchema, '');
console.log(result2.success); // false
10. safeParse()
Что делает: Основная функция для выполнения валидации. Возвращает объект результата, который содержит поле success (boolean) и либо output (валидные данные), либо issues (массив ошибок).
Параметры:
schema: схема для валидации.input: данные для проверки.
Пример:
import { string, safeParse } from 'valibot';
const result = safeParse(string(), 123);
if (!result.success) {
console.log(result.issues[0].message); // "Invalid type: Expected string but received number"
}
Реальный практический пример использования
Рассмотрим сценарий: мы разрабатываем API для интернет-магазина. Нам нужно валидировать входящие данные для создания нового заказа. Заказ содержит обязательные поля (товары, адрес доставки) и опциональные (промокод, комментарий).
import {
object, string, number, array, optional, email,
minLength, maxLength, min