Zod parse vs safeParse: Key Differences and When to Use

Zod is a powerful schema validation library that offers two primary methods to validate data: .parse and .safeParse. Both can be used synchronously or asynchronously (.parseAsync and .safeParseAsync), depending on your needs.

Define A Schema:

We’ll create a schema for a product, which includes a name, price, stock quantity, and a category.

import { z } from 'zod';

const productSchema = z.object({
  name: z.string(),
  price: z.number().positive(),
  stock: z.number().int().nonnegative(),
  category: z.enum(['Electronics', 'Books', 'Clothing', 'Toys']),
});

Zod Parse:

.parse: Immediate Error Throwing

The .parse method is straightforward—it throws an error if the data doesn’t match the schema. This is useful when you want the program to halt immediately upon invalid input, such as when validating input in middleware or inside a try-catch block

try {
  const productData = productSchema.parse({
    name: "Laptop",
    price: -1200, // Invalid: price should be positive
    stock: 10,
    category: "Electronics",
  });
  console.log("Validated Product:", productData);
} catch (error) {
  console.error("Error:", error.errors);
}

Output:

Error: [
  {
    "message": "Number must be greater than 0",
    "path": ["price"],
    "code": "too_small"
  }
]

In this example, the price field is invalid because it's negative, so .parse throws an error and halts the execution. This is helpful if you're validating data at an API endpoint and want to reject the request immediately if it's invalid.

Zod safeParse:

.safeParse: Graceful Error Handling

const result = productSchema.safeParse({
  name: "Laptop",
  price: -1200, // Invalid: price should be positive
  stock: 10,
  category: "Electronics",
});

if (!result.success) {
  console.error("Validation failed:", result.error.errors);
} else {
  console.log("Validated Product:", result.data);
}

Output:

Validation failed: [
  {
    "message": "Number must be greater than 0",
    "path": ["price"],
    "code": "too_small"
  }
]

In this case, .safeParse doesn’t throw an error, but it returns an object indicating whether validation succeeded. The rest of your code can continue running even when validation fails.

Conclusion:

  • .parse: Useful for strict validation where you need to throw an error and stop execution when the data is invalid, such as in API requests.

  • .safeParse: Provides a non-throwing validation method, ideal for cases where you want to handle errors gracefully, like in form validation or non-blocking flows.

0
Subscribe to my newsletter

Read articles from Harsh Vardhan Pandey directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Harsh Vardhan Pandey
Harsh Vardhan Pandey

I'm Harsh Vardhan Pandey, an engineering student from India. I'm a Passionate Backend Developer. I'm working on developing effective answers to Computer Science difficulties as well as Open Source projects.