Skip to content

Instantly share code, notes, and snippets.

@colinhacks
Last active March 11, 2025 19:30
Show Gist options
  • Save colinhacks/43d53a23292c4cbff7f4408ec6e618dd to your computer and use it in GitHub Desktop.
Save colinhacks/43d53a23292c4cbff7f4408ec6e618dd to your computer and use it in GitHub Desktop.

Revisions

  1. colinhacks revised this gist Mar 11, 2025. 1 changed file with 30 additions and 16 deletions.
    46 changes: 30 additions & 16 deletions meta.ts
    Original file line number Diff line number Diff line change
    @@ -10,36 +10,50 @@ z.globalRegistry.add(mySchema, { name: "foo", description: "bar" });
    // equivalent convenience method (returns mySchema)
    mySchema.meta({ name: "foo", whatever: "bar" });

    // global registry is untyped (accepts anything as metadata)
    z.globalRegistry.add(z.string(), "hello");
    z.globalRegistry.add(z.string(), 1234);
    z.globalRegistry.add(z.string(), { foo: "bar" });
    // global registry is untyped (accepts any object as metadata)
    z.globalRegistry.add(z.string(), { a: "hello" });
    z.globalRegistry.add(z.string(), { b: 1234 });

    // to retrive metadata from global registry
    z.globalRegistry.get(mySchema); // returns metadata (type is `unknown`)
    // equivalent convenience method
    mySchema.meta();

    // for typed metadata, use a custom registry
    const myRegistry = z.registry<{ name: string; description: string }>();
    // for typed custom metadata, use a custom registry
    const regA = z.registry<{ name: string; description: string }>();

    // register typed metadata
    myRegistry.add(mySchema, { name: "foo", description: "bar" });
    regA.add(mySchema, { name: "foo", description: "bar" });
    // equivalent convenience method (returns mySchema)
    mySchema.register(myRegistry, { name: "foo", description: "bar" });

    // retrive typed metadata
    myRegistry.get(mySchema);
    // => { name: string; description: string } | undefined

    mySchema.register(regA, { name: "foo", description: "bar" });
    // you can register your metadata "inline" with full typesafety
    const User = z.object({
    name: z.string().register(myRegistry, {
    const _ = z.object({
    name: z.string().register(regA, {
    name: "name",
    description: "The name of the user",
    }),
    age: z.number().register(myRegistry, {
    age: z.number().register(regA, {
    name: "age",
    description: "The age of the user",
    }),
    });

    // retrive typed metadata
    regA.get(mySchema);
    // => { name: string; description: string } | undefined

    // coupling metadata to inferred types
    // INPUT/OUTPUT is a special symbol that can be used to reference the output type of a schema
    // it gets replaces with the actual output type when the registry is used
    type B = { title: string; examples: z.OUTPUT[] };
    const regB = z.registry<B>();
    regB.add(z.string(), { title: "Name", examples: ["Alice", "Bob"] });
    regB.add(z.number(), { title: "Ages", examples: [20, 99] });

    // constraining registries by schema type
    const regC = z.core.registry<object, z.ZodObject>();
    regC.add(z.object({}), { title: "Name" });
    regC.add(z.number(), { title: "Ages" });
    // ^ ERROR: not assignable

    /** Internally registries use a weakmap to prevent memory leaks */
  2. colinhacks revised this gist Dec 5, 2024. 1 changed file with 8 additions and 14 deletions.
    22 changes: 8 additions & 14 deletions meta.ts
    Original file line number Diff line number Diff line change
    @@ -33,19 +33,13 @@ myRegistry.get(mySchema);
    // => { name: string; description: string } | undefined

    // you can register your metadata "inline" with full typesafety
    const jsonSchemaRegistry = z.registry<{ name: string; description: string }>();

    const User = z.object({
    name: z
    .string()
    .register(jsonSchemaRegistry, {
    name: "name",
    description: "The name of the user",
    }),
    age: z
    .number()
    .register(jsonSchemaRegistry, {
    name: "age",
    description: "The age of the user",
    }),
    name: z.string().register(myRegistry, {
    name: "name",
    description: "The name of the user",
    }),
    age: z.number().register(myRegistry, {
    name: "age",
    description: "The age of the user",
    }),
    });
  3. colinhacks revised this gist Dec 5, 2024. 1 changed file with 18 additions and 0 deletions.
    18 changes: 18 additions & 0 deletions meta.ts
    Original file line number Diff line number Diff line change
    @@ -31,3 +31,21 @@ mySchema.register(myRegistry, { name: "foo", description: "bar" });
    // retrive typed metadata
    myRegistry.get(mySchema);
    // => { name: string; description: string } | undefined

    // you can register your metadata "inline" with full typesafety
    const jsonSchemaRegistry = z.registry<{ name: string; description: string }>();

    const User = z.object({
    name: z
    .string()
    .register(jsonSchemaRegistry, {
    name: "name",
    description: "The name of the user",
    }),
    age: z
    .number()
    .register(jsonSchemaRegistry, {
    name: "age",
    description: "The age of the user",
    }),
    });
  4. colinhacks created this gist Dec 5, 2024.
    33 changes: 33 additions & 0 deletions meta.ts
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,33 @@
    import * as z from "zod";

    const mySchema = z.string();

    // there is a global schema registry
    z.globalRegistry; // => ZodRegistry<unknown, z.ZodType>

    // add schema to registry w/ associated metadata
    z.globalRegistry.add(mySchema, { name: "foo", description: "bar" });
    // equivalent convenience method (returns mySchema)
    mySchema.meta({ name: "foo", whatever: "bar" });

    // global registry is untyped (accepts anything as metadata)
    z.globalRegistry.add(z.string(), "hello");
    z.globalRegistry.add(z.string(), 1234);
    z.globalRegistry.add(z.string(), { foo: "bar" });

    // to retrive metadata from global registry
    z.globalRegistry.get(mySchema); // returns metadata (type is `unknown`)
    // equivalent convenience method
    mySchema.meta();

    // for typed metadata, use a custom registry
    const myRegistry = z.registry<{ name: string; description: string }>();

    // register typed metadata
    myRegistry.add(mySchema, { name: "foo", description: "bar" });
    // equivalent convenience method (returns mySchema)
    mySchema.register(myRegistry, { name: "foo", description: "bar" });

    // retrive typed metadata
    myRegistry.get(mySchema);
    // => { name: string; description: string } | undefined