colinhacks

    colinhacks/zod

    #349 this week

    TypeScript-first schema validation with static type inference

    web
    runtime-validation
    schema-validation
    static-types
    type-inference
    typescript
    TypeScript
    MIT
    43.3K stars
    2.1K forks
    43.3K GitHub watchers
    Updated 7/26/2026
    View on GitHub

    Backblaze Generative Media Hackathon

    Build the next generation of AI media apps with Genblaze, stored on Backblaze B2. $10,000 in prizes.

    Enter the hackathon

    Loading star history...

    Use Cases & Benefits

    • Zod is a TypeScript-first schema validation library enabling runtime data validation with static type inference for safer code.
    • Key features include zero dependencies, 2kb gzipped size, immutable API, JSON Schema conversion, and compatibility with Node.js and browsers.
    • Strengths are strong TypeScript integration, detailed error reporting, and async validation support; limitations include focus on TypeScript users.
    • Organizations can use Zod in production to validate and type-check API inputs, configuration files, and user data to prevent runtime errors.
    • Ideal use cases include TypeScript projects requiring runtime validation, API data validation, form input validation, and schema-driven development.

    About zod

    Zod logo

    Zod

    TypeScript-first schema validation with static type inference
    by @colinhacks


    Zod CI status License npm discord server stars

    Docs   •   Discord   •   𝕏   •   Bluesky


    jazz logo

    Learn more about featured sponsorships




    Read the docs →



    What is Zod?

    Zod is a TypeScript-first validation library. Define a schema and parse some data with it. You'll get back a strongly typed, validated result.

    import * as z from "zod";
    
    const User = z.object({
      name: z.string(),
    });
    
    // some untrusted data...
    const input = {
      /* stuff */
    };
    
    // the parsed result is validated and type safe!
    const data = User.parse(input);
    
    // so you can use it with confidence :)
    console.log(data.name);
    

    Features

    • Zero external dependencies
    • Works in Node.js and all modern browsers
    • Tiny: 2kb core bundle (gzipped)
    • Immutable API: methods return a new instance
    • Concise interface
    • Works with TypeScript and plain JS
    • Built-in JSON Schema conversion
    • Extensive ecosystem

    Installation

    npm install zod
    

    Basic usage

    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.object({
      username: z.string(),
      xp: z.number(),
    });
    

    Parsing data

    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 }
    

    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"
    

    Handling errors

    When validation fails, the .parse() method will throw a ZodError instance with granular information about the validation issues.

    try {
      Player.parse({ username: 42, xp: "100" });
    } catch (err) {
      if (err 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'
          }
        ] */
      }
    }
    

    To avoid a try/catch block, you can use the .safeParse() method to get back a plain result object containing either the successfully parsed data or a ZodError. The result type is a discriminated union, so you can handle both cases conveniently.

    const result = Player.safeParse({ username: 42, xp: "100" });
    if (!result.success) {
      result.error; // ZodError instance
    } else {
      result.data; // { username: string; xp: number }
    }
    

    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" }
    

    Inferring 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.object({
      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 };
    

    In some cases, the input & output types of a schema can diverge. For instance, the .transform() API can convert the input from one type to another. In these cases, you can extract the input and output types independently:

    const mySchema = z.string().transform((val) => val.length);
    
    type MySchemaIn = z.input<typeof mySchema>;
    // => string
    
    type MySchemaOut = z.output<typeof mySchema>; // equivalent to z.infer<typeof mySchema>
    // number
    

    Discover Repositories

    Search across tracked repositories by name or description