Skip to content

colinhacks/tozod

Repository files navigation

toZod

toZod is a utility for defining Zod schemas that agree with a TypeScript type.

This it the inverse how Zod typically works. By chaining and composing its built-in methods, Zod is able to build up an inferred static type for your schema. This is the opposite: toZod "infers" the structure of a Zod schema from a TS type.

Installation

yarn add tozod

⚠ Requires TypeScript 3.9+ and "strictNullChecks": true

Usage

import { toZod } from 'tozod';

type Player = {
  name: string;
  age?: number | undefined;
  active: boolean | null;
};

export const Player: toZod<Player> = z.object({
  name: z.string(),
  age: z.number().optional(),
  active: z.boolean().nullable(),
});

Getting rid of any of these method calls will throw a TypeError.

tozod type error screenshot

This gets extremely exciting when you start using it on recursive or mutually recursive types.

type User = {
  id: string;
  name: string;
  age?: number | undefined;
  active: boolean | null;
  posts: Post[];
};

type Post = {
  content: string;
  author: User;
};

export const User: toZod<User> = z.late.object(() => ({
  id: z.string().uuid(), // refinements are fine
  name: z.string(),
  age: z.number().optional(),
  active: z.boolean().nullable(),
  posts: z.array(Post),
}));

export const Post: toZod<Post> = z.late.object(() => ({
  content: z.string(),
  author: User,
}));

The above uses a z.late.object method that is currently implemented but undocumented.

You've just implemented two mutually recursive validatators with accurate static and runtime type information. So you can use Zod's built-in object methods to derive variants of these schemas:

const CreateUserInput = User.omit({ id: true, posts: true });
const PostIdOnly = Post.pick({ id: true });
const UpdateUserInput = User.omit({ id: true }).partial().extend({ id: z.string()u });

And because the TypeScript engine knows the exact shape of the Zod schema internally, you can access its internals like so:

User.shape.posts.element.shape.author;

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Sponsor this project

Packages

No packages published