Skip to content

Releases: colinhacks/zod

v3.11.6

Choose a tag to compare

@colinhacks colinhacks released this 26 Oct 19:39
fdd7084

Support type guards as refinements #727
Fix #732

v3.11.4

Choose a tag to compare

@colinhacks colinhacks released this 24 Oct 18:20
Add describe

v3.11.3

Choose a tag to compare

@colinhacks colinhacks released this 23 Oct 20:56

Support TypeScript 4.5.

v3.10.3

Choose a tag to compare

@colinhacks colinhacks released this 19 Oct 16:08

New parsing engine. Zod now surfaces more errors.

v3.9.8

Choose a tag to compare

@colinhacks colinhacks released this 05 Oct 19:51

v3.9.8

v3.9.0

Choose a tag to compare

@colinhacks colinhacks released this 25 Sep 22:25

✨ Zod 3.9 ✨

Custom error messages in schemas

const name = z.string({
  invalid_type_error: "Name must be string",
  required_error: "Name is required",
});

Under the hood, this creates a custom error map that's bound to the schema. You can also pass a custom error map explicitly.

const name = z.string({ errorMap: myErrorMap });

Rest parameters for tuples

const myTuple = z.tuple([z.string(), z.number()]).rest(z.boolean());
type t1 = z.output<typeof myTuple>; // [string, number, ...boolean[]]

Selective .partial

You can specify certain fields to make optional with the ZodObject.partial method.

const user = z.object({
  name: z.string(),
  age: z.number(),
});

const optionalNameUser = user.partial({ name: true });
// { name?: string; age: number; }

Support key schema in ZodRecord

Previously, z.record only accepted a single schema:

z.record(z.boolean()); // Record<string, boolean>;

Now z.record has been overloaded to support two schemas. The first validates the keys of the record, and the second validates the values.

const schema = z.record(z.number(), z.boolean());
type schema = z.infer<typeof schema>; // Record<number, boolean>

const schema = z.record(z.enum(["Tuna", "Trout"]), z.boolean());
type schema = z.infer<typeof schema>; // Record<"Tuna" | "Trout", boolean>

Don't short-circuit on some validation errors

Certain issue types "short circuit" the rest of the validation logic. If you pass a number into a ZodString schema, Zod throws an error immediately, without passing the input through any downstream refinements or transforms. This is intentional; those refinements/transforms are likely to throw unexpected errors since they assume a number input.

However other kinds of errors shouldn't "short circuit" like this. For instance z.string().min(10).email(). If we try to parse "asdf" with this schema, we should get two errors: "Invalid email" and "Input should contain at least 10 characters". If we short circuit after the "min" error, then Zod fails to surface the full set of validation issues.

Zod now considers certain classes of validation errors "continuable", in that they don't short circuit validation logic. This makes Zod more usable in form validation settings like this:

const user = z
  .object({
    password: z.string().min(6),
    confirm: z.string(),
  })
  .refine((data) => data.password === data.confirm, "Passwords don't match");
const result = user.safeParse({ password: "asdf", confirm: "qwer" });

This will return an error with two issues. Previously the parsing would have short-circuited after the inner password was invalid.

/*
ZodError: [
    {
      "code": "too_small",
      "minimum": 6,
      "type": "string",
      "inclusive": true,
      "message": "Should be at least 6 characters",
      "path": [ "password" ]
    },
    {
      "code": "custom",
      "message": "Passwords don't match",
      "path": [ "confirm" ]
    }
  ]
*/

v3.8.0

Choose a tag to compare

@colinhacks colinhacks released this 23 Aug 03:36
7fe864e

Release: zod@3.8.0
What's new:

z.preprocess

This lets you transform input data before it is parsed by your schema. This is useful for several use cases, notably type coercion. Usage:

const coercedString = z.preprocess(
  val => String(val),
  z.string()
)
mySchema.parse(12); // => "12"
mySchema.parse(true); // => "true"

CUID validation

Courtesy of @alii

const cuid = z.string().cuid()
cuid.parse("ckopqwooh000001la8mbi2im9");

Improved .deepPartial()

The .deepPartial() method on object schemas now recursively traverses through ZodArray, ZodTuple, ZodOptional, and ZodNullable elements. Previously, this method only worked in hierarchies of simple object schemas.

const mySchema = z.object({
  name: z.string(),
  array: z.array(z.object({ asdf: z.string() })),
  tuple: z.tuple([
    z.object({ value: z.string() })
  ]),
}) 

const partialed = mySchema.deepPartial();
type partialed = z.infer<typeof partialed>;
/*
  {
    name?: string | undefined;
    array?: {
        asdf?: string | undefined;
    }[] | undefined;
    tuple?: [{value?: string}] | undefined;
  }
*/

v3.7.3

Choose a tag to compare

@colinhacks colinhacks released this 19 Aug 17:25

Improve Zod stack traces

v3.7.0

Choose a tag to compare

@colinhacks colinhacks released this 01 Aug 23:23
  • Eliminate ZodNonEmptyArray, add Cardinality to ZodArray
  • Add optional error message to ZodArray.nonempty
  • Add .gt/.gte/.lt/.lte to ZodNumber, alias min -> gte and max -> lte

v3.6.1

Choose a tag to compare

@colinhacks colinhacks released this 01 Aug 03:22
  • Add IE11 support

  • ZodError.flatten now optionally accepts a map function for customizing the output

  • .void() now only accepts undefined, not null.

  • z.enum now supports Readonly string tuples

    const HTTP_SUCCESS = ["200", "201"] as const;
    const arg = z.enum(HTTP_SUCCESS);