Skip to content
masterclassBuddyTech Buzz5 fresh blogs · 5:00 AM IST

Zod · Module

.superRefine

.superRefine() adds custom validation logic to a schema and can report multiple issues. It also supports Zod's internal issue types, unlike the single custom issue produced by .refine().

How it works

.superRefine() runs custom validation after the value has been parsed and gives the callback a context for adding validation issues. Unlike .refine(), it can emit multiple issues and use Zod's internal issue types, while a type-predicate callback can narrow the inferred type.

Syntax

schema.superRefine((value, ctx) => { ctx.addIssue({ code: "custom", message: "Invalid value" }); })

Parameters

NameTypeDescription
callback(value, ctx) => voidCallback invoked with the parsed value and a context object; call ctx.addIssue() to report validation failures.

Returns

A new schema with the added refinement logic.

Key points

  • Use .superRefine() for validations that need several diagnostics or issue codes beyond custom.
  • It is chained onto an existing schema and receives the validated value plus an issue-reporting context.
  • Issue objects can use a built-in size-related code instead of representing every failure as a generic custom issue.

Common mistakes

  • Using .refine() instead limits the validation to one custom issue; use .superRefine() when several issues or built-in issue codes are needed.

Example: Validate an array with multiple issues

import { z } from "zod";

const UniqueStringArray = z.array(z.string()).superRefine((value, ctx) => {
  if (value.length > 3) {
    ctx.addIssue({
      code: "too_big",
      maximum: 3,
      origin: "array",
      inclusive: true,
      message: "Too many items",
      input: value,
    });
  }

  if (value.length !== new Set(value).size) {
    ctx.addIssue({
      code: "custom",
      message: "No duplicates allowed",
      input: value,
    });
  }
});

UniqueStringArray.parse(["a", "a", "b", "c"]);

This schema reports separate issues for exceeding the length limit and for duplicate values.

When to use it

Multi-rule validation

Validate collections with several independent constraints and return every detected problem.

Typed issue reporting

Emit a specific built-in issue type, such as an array-size failure, instead of only a generic custom error.

Type narrowing

Express a user-defined type predicate when runtime validation should narrow the inferred TypeScript type.

Interview questions

QHow does .superRefine() differ from .refine()?

.superRefine() accepts a callback receiving the parsed value and a context object. The callback calls ctx.addIssue() to report failures, and it may add more than one issue.

Follow-up: How would you report both duplicate values and an excessive array length? Use separate conditions and call ctx.addIssue() once for each failed condition.

QWhen should .superRefine() be preferred?

.superRefine() can create multiple issues and can use any of Zod's internal issue types. .refine() produces only one issue with the custom code.

Follow-up: What information can a size-related issue carry? Provide an appropriate issue code, a maximum, an origin such as array, inclusiveness, and a message.

QCan .superRefine() affect TypeScript inference?

The callback can be a type predicate, in which case Zod narrows the resulting type to the predicate's type. Otherwise, it is used to add custom validation issues without that type narrowing.

Follow-up: What is the practical risk of an inaccurate predicate? The inferred type may be narrower than the values the runtime validation truly guarantees.

  • refine
  • addIssue
  • ZodIssueCode
  • ZodError
  • type predicate

Source: Defining schemas | Zod. Checked 2026-10-15.