Zod logo

Basic usage

This page will walk you through the basics of creating schemas, parsing data, and using inferred types. For complete documentation on Zod's schema API, refer to Defining schemas.

Defining a schema

Before you can do anything else, you need to define a schema. For the purposes of this guide, we'll use a simple object schema.

import * as z from "zod"; 
 
const Player = z.interface({ 
  username: z.string(),
  xp: z.number()
});

Parsing data

Now that we have a schema, we can parse some data with it.

.parse()

.parse(data: unknown): T

Given any Zod schema, use .parse to validate an input. If it's valid, Zod returns a strongly-typed deep clone of the input.

Player.parse({ username: "billie", xp: 100 }); 
// => returns { username: "billie", xp: 100 }

Otherwise, a ZodError instance is thrown with detailed information about the validation issues.

try {
  Player.parse({ username: 42, xp: "100" });
} catch(err){
  if(error instanceof z.ZodError){
    err.issues; 
    /* [
      {
        expected: 'string',
        code: 'invalid_type',
        path: [ 'username' ],
        message: 'Invalid input: expected string'
      },
      {
        expected: 'number',
        code: 'invalid_type',
        path: [ 'xp' ],
        message: 'Invalid input: expected number'
      }
    ] */
  }
}

Note — If your schema uses certain asynchronous APIs like async refinements or transforms, you'll need to use the .parseAsync() method instead.

const schema = z.string().refine(async (val) => val.length <= 8);
 
await schema.parseAsync("hello");
// => "hello"

.safeParse()

.safeParse(data:unknown): { success: true; data: T; } | { success: false; error: ZodError; }

To avoid try/catch blocks, use .safeParse(). This method returns an object containing either the successfully parsed data or a ZodError.

Player.safeParse({ username: "billie", xp: 100 });
// => { success: true; data: { username: "billie", xp: 100 } }
 
Player.safeParse({ username: 42, xp: "100" });
// => { success: false; error: ZodError }

The result type is a discriminated union, so you can handle both cases conveniently:

const result = stringSchema.safeParse("billie");
if (!result.success) {
  result.error;   // handle error
} else {
  result.data;    // do stuff
}

Note — If your schema uses certain asynchronous APIs like async refinements or transforms, you'll need to use the .safeParseAsync() method instead.

const schema = z.string().refine(async (val) => val.length <= 8);
 
await schema.safeParseAsync("hello");
// => { success: true; data: "hello" }

Inferred types

Zod infers a static type from your schema definitions. You can extract this type with the z.infer<> utility and use it however you like.

const Player = z.interface({ 
  username: z.string(),
  xp: z.number()
});
 
// extract the inferred type
type Player = z.infer<typeof Player>;
 
// use it in your code
const player: Player = { username: "billie", xp: 100 };

Now that we have the basics covered, let's jump into the Schema API.

On this page