RepoPilot

How do I define a custom validator in zod?

About colinhacks/zod · 2 messages · last activity 7/12/2026

Question

How do I define a custom validator in zod?

RepoPilot

Perfect! Zod provides the .refine() method for custom validators. Based on the source code, here's how to use it:

Custom Validators with .refine()

The .refine() method allows you to add custom validation logic to any Zod schema [packages/zod/src/v3/types.ts:L318-L357].

Basic syntax:

schema.refine(
  check: (value) => boolean | Promise<boolean>,
  message?: string | CustomErrorParams | ((value) => CustomErrorParams)
)

Parameters:

  • check: A function that receives the parsed value and returns a boolean (or Promise<boolean>). Return true if valid, false if invalid.
  • message (optional): An error message, a function that generates error properties, or a custom error params object.

Example:

z.string()
  .refine((val) => val.length > 0, "Cannot be empty")
  .refine((val) => val.startsWith("A"), "Must start with A")

Async validation:

z.string()
  .refine(async (val) => {
    // Call API, database, etc.
    const isValid = await checkUsername(val);
    return isValid;
  }, "Username already taken")

Custom error object:

z.object({ password: z.string(), confirm: z.string() })
  .refine((val) => val.password === val.confirm, {
    message: "Passwords don't match",
    path: ["confirm"], // Set which field the error appears on
  })

The .refine() method returns a ZodEffects schema that wraps your original schema with the additional validation logic.

FOLLOW_UPS:

  • How do I use superRefine() for advanced customization?
  • Can I add multiple validation checks to one schema?
  • How do I handle async validation with .refine()?

Want to ask your own question?

Open chat for colinhacks/zod

Public Q&A. Generated by RepoPilot from the actual source of colinhacks/zod. AI answers can be incomplete or stale — verify before relying on them.