Recipe
Yup Schema Patterns
Composable validation schemas for form state, API boundaries, and runtime type safety.
Shape composition
const base = object({
email: string().email().required(),
age: number().min(13).max(120),
})
const extended = base.shape({
username: string().min(3).required(),
})Conditional validation
const schema = object({
paymentMethod: string().oneOf(['card','crypto']),
cardNumber: string().when('paymentMethod', {
is: 'card',
then: (s) => s.required().matches(/^\d{16}$/),
otherwise: (s) => s.strip(),
}),
})Transform & cast
const price = number()
.transform((v) => Math.round(v * 100) / 100)
.typeError('Must be a number')
const tags = string()
.transform((v) => v.split(',').map((t) => t.trim()))
.test('max-tags', 'Max 5 tags', (arr) => arr.length <= 5)Custom test with context
const unique = string().test(
'unique-username',
'Username taken',
async (value, ctx) => {
const exists = await checkAvailability(value)
return !exists
}
)Error extraction
try {
await schema.validate(data, { abortEarly: false })
} catch (err) {
const fieldErrors = err.inner.reduce((acc, e) => {
acc[e.path] = e.message
return acc
}, {})
}Tip: Co-locate schemas with your form components. Export the inferred type via InferType<typeof schema> for end-to-end type safety without duplication.