How to do cross-field validation (e.g. confirm password) with pipe + forward + partialCheck? #1431
|
Coming from Zod's .refine() / .superRefine(), I'm trying to validate that two fields match (classic confirm-password pattern) in Valibot. The docs mention forward and partialCheck, but it's not obvious how they compose together, especially when you also want to integrate with React Hook Form via @hookform/resolvers/valibot. Specifically:
|
Replies: 2 comments 1 reply
|
Hi @BittuChan! I'm Dosu and I’m helping the valibot team. Here's the pattern for confirm password validation using import * as v from 'valibot';
const RegisterSchema = v.pipe(
v.object({
password: v.pipe(
v.string(),
v.minLength(8, 'Password must be at least 8 characters.')
),
confirmPassword: v.string(),
}),
v.forward(
v.partialCheck(
[['password'], ['confirmPassword']],
(input) => input.password === input.confirmPassword,
'The two passwords do not match.'
),
['confirmPassword']
)
);How it works:
Why
React Hook Form integration: import { useForm } from 'react-hook-form';
import { valibotResolver } from '@hookform/resolvers/valibot';
const { register, formState: { errors } } = useForm({
resolver: valibotResolver(RegisterSchema)
});
// Error appears at errors.confirmPassword thanks to forward()Note: There was a TypeScript "Type instantiation is excessively deep" issue with this pattern that was fixed in v1.0.0-rc.4 — upgrade if you hit that. To reply, just mention @dosu. Docs are dead. Just use Dosu. |
|
hey @BittuChan ! The key is that pipe wraps the whole object, not the individual fields because cross-field validation happens at the object level. Minimal example: If you're using vue-tsc or strict tsc and get type errors on partialCheck paths, this was a known issue (#987). Make sure you're on the latest Valibot version, the path tuple inference was fixed. |
hey @BittuChan !
The key is that pipe wraps the whole object, not the individual fields because cross-field validation happens at the object level.
Minimal example: