> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/colinhacks/zod/llms.txt
> Use this file to discover all available pages before exploring further.

# Quick Start

> Learn Zod fundamentals in 5 minutes

This guide walks you through the core concepts of Zod: defining schemas, parsing data, type inference, and error handling.

## Schema Definition

A schema defines the shape and validation rules for your data. Start by defining a simple object schema:

```typescript theme={null}
import * as z from "zod";

const Player = z.object({
  username: z.string(),
  xp: z.number(),
});
```

You can build more complex schemas by composing primitive types:

```typescript theme={null}
const User = z.object({
  name: z.string(),
  age: z.number(),
  email: z.optional(z.string()),
  isAdmin: z.boolean(),
});
```

<Tip>
  Schemas are immutable. Methods like `.check()` and `.optional()` return new schema instances.
</Tip>

## Parsing Data

<Steps>
  <Step title="Use .parse() for validation">
    The `.parse()` method validates input and returns a deep clone if valid. It throws a `ZodError` if validation fails:

    ```typescript theme={null}
    const Player = z.object({
      username: z.string(),
      xp: z.number(),
    });

    // Valid input
    const result = Player.parse({ username: "billie", xp: 100 });
    console.log(result);
    // => { username: "billie", xp: 100 }
    ```
  </Step>

  <Step title="Handle validation errors">
    When parsing fails, Zod throws a detailed error:

    ```typescript theme={null}
    try {
      Player.parse({ username: 42, xp: "100" });
    } catch (err) {
      if (err instanceof z.ZodError) {
        console.log(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'
          }
        ] */
      }
    }
    ```
  </Step>

  <Step title="Use .safeParse() to avoid exceptions">
    For error handling without try/catch, use `.safeParse()`. It returns a discriminated union:

    ```typescript theme={null}
    const result = Player.safeParse({ username: 42, xp: "100" });

    if (!result.success) {
      // result.error is a ZodError instance
      console.log(result.error.issues);
    } else {
      // result.data has the correct type: { username: string; xp: number }
      console.log(result.data);
    }
    ```
  </Step>
</Steps>

## Type Inference

Zod automatically infers TypeScript types from your schemas using `z.infer<>` or `z.output<>`:

```typescript theme={null}
const Player = z.object({
  username: z.string(),
  xp: z.number(),
});

// Extract the TypeScript type
type Player = z.infer<typeof Player>;
// type Player = {
//   username: string;
//   xp: number;
// }

// Use the inferred type
const player: Player = { username: "billie", xp: 100 };
```

<Note>
  For schemas with transformations, use `z.input<>` to get the input type and `z.output<>` (or `z.infer<>`) to get the output type.
</Note>

### Input vs Output Types

When you use transforms, input and output types can differ:

```typescript theme={null}
const StringToNumber = z.string().check(
  z.refine((val) => !isNaN(Number(val)))
);

type Input = z.input<typeof StringToNumber>;  // string
type Output = z.output<typeof StringToNumber>; // string
```

## Error Handling

Zod provides detailed error information when validation fails.

### Working with ZodError

Every failed parse produces a `ZodError` with an `issues` array:

```typescript theme={null}
const result = z.string().safeParse(123);

if (!result.success) {
  console.log(result.error.issues);
  // [{
  //   code: 'invalid_type',
  //   expected: 'string',
  //   received: 'number',
  //   path: [],
  //   message: 'Invalid input'
  // }]
}
```

### Custom Error Messages

You can provide custom error messages when defining schemas:

```typescript theme={null}
const Email = z.email("Please provide a valid email address");

const result = Email.safeParse("invalid-email");
if (!result.success) {
  console.log(result.error.issues[0].message);
  // => "Please provide a valid email address"
}
```

Or use a function for dynamic messages:

```typescript theme={null}
const Email = z.email({
  error: () => "Please provide a valid email address"
});
```

## Complete Example

Here's a complete example combining all concepts:

```typescript theme={null}
import * as z from "zod";

// Define the schema
const UserSchema = z.object({
  name: z.string(),
  age: z.number(),
  email: z.optional(z.email("Invalid email format")),
});

// Infer the TypeScript type
type User = z.infer<typeof UserSchema>;

// Parse some data
const input = {
  name: "John Doe",
  age: 30,
  email: "john@example.com",
};

const result = UserSchema.safeParse(input);

if (result.success) {
  // Type-safe access to validated data
  const user: User = result.data;
  console.log(`Welcome, ${user.name}!`);
} else {
  // Handle validation errors
  console.error("Validation failed:");
  result.error.issues.forEach((issue) => {
    console.error(`- ${issue.path.join('.')}: ${issue.message}`);
  });
}
```

## Next Steps

<CardGroup cols={2}>
  <Card title="Primitives" icon="shapes" href="/api/primitives/string">
    Explore all primitive types: strings, numbers, dates, and more
  </Card>

  <Card title="Objects" icon="cubes" href="/api/complex/object">
    Learn about object schemas, nesting, and composition
  </Card>

  <Card title="Arrays & Tuples" icon="list" href="/api/complex/array">
    Work with arrays, tuples, and collections
  </Card>

  <Card title="Advanced Types" icon="wand-magic-sparkles" href="/api/complex/union">
    Master unions, intersections, and discriminated unions
  </Card>
</CardGroup>
