yup
Validates data with Yup schema builder using chainable methods, custom rules, and TypeScript inference. Use when validating forms with React Hook Form or Formik, or when needing flexible schema validation.
安装与使用
请根据来源仓库和你的 AI 工具说明安装此技能。先阅读技能文件和依赖要求,再添加到工作流。
查看来源 ↗使用指南技能说明
Yup
Schema validation library with a fluent, chainable API for JavaScript and TypeScript.
Quick Start
npm install yup
import * as yup from 'yup';
const schema = yup.object({
name: yup.string().required(),
email: yup.string().email().required(),
age: yup.number().positive().integer(),
});
// Validate
const data = await schema.validate({ name: 'John', email: 'john@example.com' });
// Check validity
const isValid = await schema.isValid(data);
Schema Types
String
yup.string()
.required('Name is required')
.min(2, 'At least 2 characters')
.max(50, 'At most 50 characters')
.matches(/^[a-zA-Z]+$/, 'Only letters')
.email('Invalid email')
.url('Invalid URL')
.uuid('Invalid UUID')
.lowercase()
.uppercase()
.trim()
.default('Anonymous')
Number
yup.number()
.required('Required')
.min(0, 'Must be positive')
.max(100, 'Max 100')
.positive('Must be positive')
.negative('Must be negative')
.integer('Must be integer')
.moreThan(0, 'Greater than 0')
.lessThan(100, 'Less than 100')
.truncate()
.round()
.default(0)
Boolean
yup.boolean()
.required()
.isTrue('Must accept terms')
.isFalse()
.default(false)
Date
yup.date()
.required()
.min(new Date(), 'Must be in the future')
.max(new Date('2030-12-31'), 'Too far ahead')
.default(() => new Date())
Array
yup.array()
.of(yup.string().required())
.min(1, 'At least one item')
.max(5, 'At most 5 items')
.required()
.default([])
// Tuple-like array
yup.tuple([
yup.string().required(),
yup.number().required(),
])
Object
yup.object({
name: yup.string().required(),
age: yup.number().positive(),
})
.noUnknown() // Reject unknown keys
.strict() // Don't coerce types
Mixed (Any Type)
yup.mixed()
.oneOf(['option1', 'option2'], 'Must be option1 or option2')
.notOneOf(['forbidden'])
.required()
Common Patterns
User Registration
const registrationSchema = yup.object({
email: yup.string()
.email('Invalid email')
.required('Email is required'),
password: yup.string()
.min(8, 'At least 8 characters')
.matches(/[a-z]/, 'Need lowercase letter')
.matches(/[A-Z]/, 'Need uppercase letter')
.matches(/[0-9]/, 'Need number')
.required('Password is required'),
confirmPassword: yup.string()
.oneOf([yup.ref('password')], 'Passwords must match')
.required('Confirm password'),
age: yup.number()
.positive()
.integer()
.min(18, 'Must be 18+')
.required('Age is required'),
terms: yup.boolean()
.isTrue('Must accept terms'),
});
Address
const addressSchema = yup.object({
street: yup.string().required(),
city: yup.string().required(),
state: yup.string().length(2).required(),
zip: yup.string()
.matches(/^\d{5}(-\d{4})?$/, 'Invalid ZIP')
.required(),
country: yup.string().default('US'),
});
Payment
const paymentSchema = yup.object({
cardNumber: yup.string()
.matches(/^\d{16}$/, 'Invalid card number')
.required(),
expiry: yup.string()
.matches(/^(0[1-9]|1[0-2])\/\d{2}$/, 'MM/YY format')
.required(),
cvv: yup.string()
.matches(/^\d{3,4}$/, 'Invalid CVV')
.required(),
amount: yup.number()
.positive()
.required(),
});
Conditional Validation
when() - Field Dependencies
const schema = yup.object({
hasCompany: yup.boolean(),
companyName: yup.string().when('hasCompany', {
is: true,
then: (schema) => schema.required('Company name required'),
otherwise: (schema) => schema.notRequired(),
}),
});
Multiple Conditions
const schema = yup.object({
type: yup.string().oneOf(['personal', 'business']),
taxId: yup.string(),
ssn: yup.string(),
}).test('tax-info', 'Tax info required', function(value) {
if (value.type === 'business') {
return !!value.taxId;
}
return !!value.ssn;
});
Custom Validation
test() Method
const schema = yup.string().test(
'is-valid-username',
'Username already taken',
async (value) => {
if (!value) return true;
const available = await checkUsername(value);
return available;
}
);
With Context
const schema = yup.object({
password: yup.string().required(),
confirmPassword: yup.string()
.test('passwords-match', 'Passwords must match', function(value) {
return value === this.parent.password;
}),
});
addMethod() - Reusable Validators
yup.addMethod(yup.string, 'phone', function(message) {
return this.test('phone', message || 'Invalid phone', (value) => {
if (!value) return true;
return /^\+?[\d\s-()]+$/.test(value);
});
});
// Usage
const schema = yup.object({
phone: yup.string().phone('Invalid phone number'),
});
Type Inference
InferType
const userSchema = yup.object({
name: yup.string().required(),
email: yup.string().email().required(),
age: yup.number().positive(),
});
type User = yup.InferType<typeof userSchema>;
// { name: string; email: string; age: number | undefined }
With Defaults
const schema = yup.object({
role: yup.string().default('user'),
active: yup.boolean().default(true),
});
type Config = yup.InferType<typeof schema>;
// { role: string; active: boolean }
Transformation
cast() - Transform Values
const schema = yup.string().trim().lowercase();
const result = schema.cast(' HELLO '); // 'hello'
transform() - Custom Transforms
const schema = yup.string().transform((value) => {
return value?.replace(/\s+/g, ' ').trim();
});
Object Transform
const schema = yup.object({
firstName: yup.string(),
lastName: yup.string(),
}).transform((value) => ({
...value,
fullName: `${value.firstName} ${value.lastName}`,
}));
Validation Options
validate()
try {
const result = await schema.validate(data, {
abortEarly: false, // Collect all errors
stripUnknown: true, // Remove unknown keys
strict: false, // Allow coercion
context: { user: currentUser },
});
} catch (err) {
if (err instanceof yup.ValidationError) {
console.log(err.errors); // All error messages
console.log(err.inner); // Detailed errors
}
}
validateSync()
try {
const result = schema.validateSync(data);
} catch (err) {
// Handle error
}
isValid()
const valid = await schema.isValid(data);
React Hook Form Integration
import { useForm } from 'react-hook-form';
import { yupResolver } from '@hookform/resolvers/yup';
const schema = yup.object({
email: yup.string().email().required(),
password: yup.string().min(8).required(),
});
type FormData = yup.InferType<typeof schema>;
function Form() {
const { register, handleSubmit, formState: { errors } } = useForm<FormData>({
resolver: yupResolver(schema),
});
return (
<form onSubmit={handleSubmit(onSubmit)}>
<input {...register('email')} />
{errors.email && <span>{errors.email.message}</span>}
<input {...register('password')} type="password" />
{errors.password && <span>{errors.password.message}</span>}
<button type="submit">Submit</button>
</form>
);
}
Formik Integration
import { Formik, Form, Field, ErrorMessage } from 'formik';
const schema = yup.object({
email: yup.string().email().required(),
});
function MyForm() {
return (
<Formik
initialValues={{ email: '' }}
validationSchema={schema}
onSubmit={handleSubmit}
>
<Form>
<Field name="email" type="email" />
<ErrorMessage name="email" />
<button type="submit">Submit</button>
</Form>
</Formik>
);
}
See references/methods.md for complete method reference.
使用示例
查看来源仓库中的使用示例与配置说明。
查看来源 ↗来源历史
- 收录时间
- 2026-01-20
- 索引更新时间
- 2026-01-28
- Branch
- main
收录与同步日期属于本站记录。源码修改历史请查看来源仓库。
GitHub ↗chat Comments (0)
Sign in to join the discussion and leave a comment.
No comments yet. Be the first to share your thoughts!