Published on

How to Check and Validate Confirm Password with Zod

Authors
  • Name
    Ripal & Zalak
    Twitter

How to Check and Validate Confirm Password with Zod

Zod provides a flexible way to validate schemas. To validate that the "confirm password" matches the "password," you can use refine or superRefine. Let's explore both approaches.

Example 1: Using superRefine

The superRefine method allows for complex validations, such as cross-field checks. Here's how you can validate passwords using it:

import { z } from 'zod'

export const registerUserSchema = z
  .object({
    firstName: z.string(),
    lastName: z.string(),
    userName: z.string(),
    email: z.string().email(),
    phone: z.string().transform((data) => Number(data)),
    password: z.string().min(4, 'Password must be at least 4 characters long'),
    confirmPassword: z.string().min(4, 'Confirm password must be at least 4 characters long'),
  })
  .superRefine(({ password, confirmPassword }, ctx) => {
    if (confirmPassword !== password) {
      ctx.addIssue({
        code: 'custom',
        message: 'Passwords do not match',
        path: ['confirmPassword'],
      })
    }
  })

// Usage Example
try {
  registerUserSchema.parse({
    firstName: 'John',
    lastName: 'Doe',
    userName: 'johndoe',
    email: '[email protected]',
    phone: '1234567890',
    password: 'password123',
    confirmPassword: 'password123',
  })
  console.log('Validation successful')
} catch (e) {
  console.error(e.errors)
}

Example 2: Using refine

Alternatively, you can use the refine method for simpler checks:

const passwordForm = z
  .object({
    password: z.string().min(4),
    confirmPassword: z.string().min(4),
  })
  .refine((data) => data.password === data.confirmPassword, {
    message: "Passwords don't match",
    path: ['confirmPassword'],
  })

// Usage Example
try {
  passwordForm.parse({
    password: '1234',
    confirmPassword: '1234',
  })
  console.log('Passwords match')
} catch (e) {
  console.error(e.errors)
}

Best Practices

  • Always validate password strength: Use z.string().min(length) for minimum length and custom error messages.
  • Show error messages near fields: Use the path property in addIssue to highlight specific field errors.
  • Combine validations: Leverage Zod’s chaining capabilities to validate multiple constraints in a single schema.

FAQ

1. Why use superRefine instead of refine?

superRefine provides greater flexibility for complex validations. It allows you to access the context (ctx) for adding detailed error messages and handling multiple issues simultaneously.

2. Can I use Zod with React Hook Form?

Yes! Zod integrates seamlessly with libraries like React Hook Form. Use zodResolver from @hookform/resolvers to handle validations.

3. How can I validate other cross-field dependencies?

You can use refine or superRefine to validate any field relationships. For example, checking that a start date is before an end date in a booking form.

const bookingForm = z
  .object({
    startDate: z.date(),
    endDate: z.date(),
  })
  .refine((data) => data.startDate < data.endDate, {
    message: 'Start date must be before end date',
    path: ['endDate'],
  })