Yup - Quick Reference
Full Reference: See advanced.md for conditional validation (.when), custom validation (.test), Formik/React Hook Form integration, transforms, and localization.
Deep Knowledge: Use mcp__documentation__fetch_docs with technology: yup for comprehensive documentation.
Setup
npm install yup
Basic Usage
import * as yup from 'yup';
const userSchema = yup.object({ name: yup.string().required().min(2).max(50), email: yup.string().required().email(), age: yup.number().required().min(18).max(120).integer(), bio: yup.string().optional(), });
// Type inference type User = yup.InferType<typeof userSchema>;
// Validate async function validateUser(data: unknown) { try { const user = await userSchema.validate(data, { abortEarly: false }); return { success: true, data: user }; } catch (error) { if (error instanceof yup.ValidationError) { return { success: false, errors: error.errors }; } throw error; } }
Schema Types
String
const stringSchema = yup .string() .required('Name is required') .min(2, 'Too short') .max(100, 'Too long') .trim() .email('Invalid email') .url('Invalid URL') .matches(/^[a-zA-Z]+$/, 'Only letters allowed') .oneOf(['option1', 'option2'], 'Must be one of the options');
Number
const numberSchema = yup .number() .required() .min(0) .max(100) .positive() .integer() .typeError('Must be a number');
Date
const dateSchema = yup .date() .required() .min(new Date('2020-01-01'), 'Too old') .max(new Date(), 'Cannot be in future');
Array
const arraySchema = yup .array() .of(yup.string().required()) .required() .min(1, 'At least one item') .max(10, 'Maximum 10 items') .ensure(); // Transform null/undefined to []
Object
const objectSchema = yup.object({ name: yup.string().required(), address: yup.object({ street: yup.string().required(), city: yup.string().required(), }), }).noUnknown(true); // Strip unknown keys
// Partial object (all fields optional) const partialSchema = objectSchema.partial();
Validation Options
const result = await schema.validate(data, { abortEarly: false, // Return all errors, not just first stripUnknown: true, // Remove unknown keys strict: false, // Allow type coercion });
// Sync validation schema.validateSync(data); schema.isValidSync(data); // Returns boolean
Comparison: Yup vs Zod
Feature Yup Zod
Type inference Good Excellent
Bundle size ~12KB ~8KB
Async validation Built-in .parseAsync()
Formik Native Via resolver
Conditional .when() .refine()
When NOT to Use This Skill
-
New projects - Prefer Zod for better TypeScript integration
-
NestJS applications - Use class-validator with decorators
-
Non-form validation - Zod has better API for general validation
Anti-Patterns
Anti-Pattern Why It's Bad Correct Approach
Schema in component Re-created on render Define at module level
Forgetting abortEarly: false Only shows first error Set abortEarly: false
No custom messages Generic errors Add custom message to each
Not using InferType Manual type definitions Use yup.InferType
Quick Troubleshooting
Issue Cause Solution
Type errors with InferType Missing import Import type from 'yup'
Async validation not working Using validateSync Use .validate() (async)
"Value is required" unexpectedly Undefined vs null Use .nullable() or .optional()
Error messages not showing abortEarly: true Set abortEarly: false
Production Checklist
-
Schema defined at module level
-
Type inference with InferType
-
Custom error messages
-
abortEarly: false for forms
-
Resolver for form library
-
Localization if multilingual
Reference Documentation
- Yup GitHub