zod-class
v0.0.15
Published
Create classes from Zod Object schemas all in one line
Downloads
67,002
Readme
zod-class
This is a small utility library to accompany Zod that enables Types and Schemas to be defined in one line by creating a Class.
Installation
npm install zod-class
Usage
- Define a new 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",
});
- Parse a value to an instance of a ZodClass
const hello = Hello.parse(someVal)
// use method on the instance
const message = hello.getMessage();
- Extend a class
export class World extends Hello.extend({
world: z.string()
}) {}
const world = new World({
hello: "world",
world: "hello"
});
- Access A ZodClass's property to re-use in other schemas
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
Why?
It can be annoying to always have redundant declarations for types and schemas:
- the
z.object
declaration - the derived type using
z.infer
interface 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}`;
}
}
Workarounds
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 ZodClass
ZodClass 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