sam-goodwin/zod-class(opens in a new tab)
Language: TypeScript
Create a Class from a ZodObject schema in one line
- stars
- 59
- watchers
- 1
- forks
- 11
- open issues
- 9
- Last updated
- 03/05/2025
Language: TypeScript
Create a Class from a ZodObject schema in one line
This is a small utility library to accompany Zod that enables Types and Schemas to be defined in one line by creating a Class.
npm install zod-class
import z from "zod"; import { Z } from "zod-class"; // define a class using a zod schema export class Hello extends Z.class({ name: z.string(), }) { get getMessage() { return `hello ${name}` } } const hello = new Hello({ hello: "sam", });
const hello = Hello.parse(someVal) // use method on the instance const message = hello.getMessage();
export class World extends Hello.extend({ world: z.string() }) {} const world = new World({ hello: "world", world: "hello" });
import { z } from "zod"; import { Z } from "zod-class"; export class Product extends Z.class({ id: z.string().brand<"ProductId">, price: z.number().min(1) }) {} export class Order extends Z.class({ id: z.string().brand<"OrderId">, productId: Product.shape.id // 👈 Re-using the branded type `id` from `Product` class }) {} Product.Id // 👈 Properties are also available in friendly pascal case directly on the class constructor
It can be annoying to always have redundant declarations for types and schemas:
z.object declarationz.inferinterface HelloSchema extends z.infer<typeof HelloSchema> {} const HelloSchema = z.object({ key: z.string(), });
zod-class enables this to be achieved in a single line.
It also provides a class that can be instantiated and methods added to.
export class Person extends Z.class({ firstName: z.string(), lastName: z.string(), }) { get fullName() { return `${this.firstName} ${this.lastName}`; } }
Creating a class that adequately sub-types a Zod Schema is difficult because of how Zod is implemented. zod-class covers the most common use-cases but there are holes.
If you encounter a problem with type errors, you can always workaround it with the schema() method.
For example, if you have a function that expects a ZodType<T>:
function createDTO<T>(schema: ZodType<T>): DTO<T>;
And a class, User, constructed with Z.class:
class User extends Z.class({ username: z.string() }) {}
You should be able to just pass User in
const UserDTO = createDTO(User);
In some cases, this can error. To workaround, call User.schema() instead:
const UserDTO = createDTO(User.schema());
See relevant issue: #17
nullish will not create a schema that returns an instance of the ZodClassZodClass does not provide a type-safe implementation of schema.nullish().
User.nullish().parse(value)
This will not return an instance of User:
{ username: string } | null | undefined
Workaround with User.schema()
User.schema().nullish().parse(value) // User | null | undefined