Dead simple Object schema validation
Yup is a JavaScript schema validation library that enables developers to define and enforce data structure rules through a declarative, chainable API. With over 9 million weekly downloads, it has become the de facto standard for client-side validation, particularly in React form libraries like Formik and React Hook Form. The library creates immutable schema objects that specify types, constraints, and transformations, returning validated data or throwing detailed ValidationError objects.
The core design philosophy revolves around composability and readability. Methods like .required(), .min(), .email(), and .matches() return new schema instances, allowing fluent chaining such as yup.string().email().required(). Yup supports complex scenarios including nested object validation, conditional rules via .when(), cross-field dependencies using yup.ref(), and dynamic schemas with yup.lazy(). The library handles all primitive types (string, number, boolean, date) plus complex structures (objects, arrays) with full TypeScript support through the InferType utility.
Originally inspired by Joi's validation patterns, Yup was built specifically for browser environments where bundle size and integration with UI frameworks matter. Unlike server-focused alternatives, it prioritizes developer experience with clear error messages, schema reusability through .concat(), .pick(), and .omit(), and straightforward async validation. The library's immutable approach ensures schemas can be safely shared across components without side effects.
Yup excels in scenarios requiring readable validation logic and tight integration with React ecosystems. While newer alternatives like Zod offer superior TypeScript inference and smaller bundles, Yup's maturity, extensive documentation, and proven track record make it a reliable choice for form validation, API payload verification, and configuration object parsing in production applications.
import * as yup from 'yup';
// Define a registration form schema with conditional validation
const registrationSchema = yup.object({
username: yup.string()
.min(3, 'Username must be at least 3 characters')
.max(20, 'Username cannot exceed 20 characters')
.matches(/^[a-zA-Z0-9_]+$/, 'Only alphanumeric and underscore allowed')
.required('Username is required'),
email: yup.string()
.email('Invalid email format')
.required('Email is required'),
age: yup.number()
.positive('Age must be positive')
.integer('Age must be a whole number')
.min(18, 'Must be at least 18 years old')
.required('Age is required'),
password: yup.string()
.min(8, 'Password must be at least 8 characters')
.matches(/[A-Z]/, 'Must contain at least one uppercase letter')
.matches(/[0-9]/, 'Must contain at least one number')
.required('Password is required'),
confirmPassword: yup.string()
.oneOf([yup.ref('password')], 'Passwords must match')
.required('Confirm password is required'),
newsletter: yup.boolean().default(false),
// Conditionally require phone when newsletter is true
phone: yup.string()
.when('newsletter', {
is: true,
then: (schema) => schema
.matches(/^\+?[1-9]\d{1,14}$/, 'Invalid phone number')
.required('Phone required for newsletter'),
otherwise: (schema) => schema.nullable()
})
});
// TypeScript type inference
type RegistrationData = yup.InferType<typeof registrationSchema>;
// Validate user input
async function handleRegistration(formData: unknown) {
try {
const validatedData = await registrationSchema.validate(formData, {
abortEarly: false, // Collect all errors, not just first
stripUnknown: true // Remove fields not in schema
});
console.log('Valid data:', validatedData);
// Proceed with registration logic
} catch (error) {
if (error instanceof yup.ValidationError) {
const errors = error.inner.map(err => ({
field: err.path,
message: err.message
}));
console.error('Validation failed:', errors);
}
}
}
// Example usage
handleRegistration({
username: 'john_doe',
email: 'john@example.com',
age: 25,
password: 'SecurePass123',
confirmPassword: 'SecurePass123',
newsletter: true,
phone: '+12025551234'
});Form Validation in React Applications: Integrate with Formik or React Hook Form to validate user input before submission. Define schemas for registration forms with email format checks, password strength requirements, and field dependencies (e.g., confirming passwords match using yup.ref()).
API Request/Response Validation: Validate incoming request payloads in Express or Next.js API routes to ensure data integrity before processing. Parse and transform API responses from third-party services to guarantee expected structure and types, catching schema mismatches early.
Configuration File Parsing: Validate environment variables, JSON config files, or user settings objects at application startup. Apply defaults, coerce types, and enforce required fields to prevent runtime errors from malformed configuration.
Dynamic Multi-Step Forms: Build wizards or multi-page forms where validation rules change based on previous answers. Use .when() to conditionally require fields (e.g., show address fields only when "shipping differs from billing" is checked).
Data Transformation Pipelines: Sanitize and normalize user input by combining validation with transformations. Strip whitespace, convert strings to numbers, format dates, and apply business logic transformations while ensuring data validity in a single schema definition.
Object schema validation
The modular and type safe schema library for validating structural data
TypeScript-first schema declaration and validation library with static type inference
npm install yuppnpm add yupbun add yup