github colinhacks/zod v3.9.0

latest releases: v3.23.4, v3.23.3, v3.23.2...
2 years ago

✨ 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" ]
    }
  ]
*/

Don't miss a new zod release

NewReleases is sending notifications on new releases.