JSPM

  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 73697
  • Score
    100M100P100Q143839F
  • License MIT

Create classes from Zod Object schemas all in one line

Package Exports

    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

    1. 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",
    });
    1. Parse a value to an instance of a ZodClass
    const hello = Hello.parse(someVal)
    
    // use method on the instance 
    const message = hello.getMessage();
    1. Extend a class
    export class World extends Hello.extend({
      world: z.string()
    }) {}
    
    const world = new World({
      hello: "world",
      world: "hello"
    });
    1. 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:

    1. the z.object declaration
    2. 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

    1. 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