Refinements & Custom Validation
Write custom validation logic, cross-field assertions, and asynchronous database checks.
Single Predicate: .refine()
Supply a predicate returning boolean (or Promise<boolean>) and an error message:
Schema Definition
const EvenNumber = infer.number().refine(
(n) => n % 2 === 0,
"Number must be even"
);Multi-Issue: .superRefine()
Use .superRefine() to report issues at specific object paths, such as password confirmation checks:
Schema Definition
const PasswordForm = infer.object({
password: infer.string().min(8),
confirm: infer.string()
}).superRefine((data, ctx) => {
if (data.password !== data.confirm) {
ctx.addIssue({
code: "custom",
path: ["confirm"],
message: "Passwords do not match"
});
}
});Asynchronous Refinements
Refinements can return Promises (e.g. database lookups). Remember to execute async schemas with .parseAsync() or .safeParseAsync().
Schema Definition
const UniqueUsername = infer.string().refine(
async (username) => {
const taken = await checkDb(username);
return !taken;
},
"Username already taken"
);
const res = await UniqueUsername.safeParseAsync("alice");