Coder Social home page Coder Social logo

Comments (8)

FlorianWendelborn avatar FlorianWendelborn commented on May 23, 2024 1

Then I think this should just be documented that this package handles z.input and not z.output aka z.infer

from zod-to-json-schema.

StefanTerdell avatar StefanTerdell commented on May 23, 2024

Hello! Care to elaborate with an example?

from zod-to-json-schema.

FlorianWendelborn avatar FlorianWendelborn commented on May 23, 2024

@StefanTerdell sure, here’s the documentation section for z.input/z.output: https://github.com/colinhacks/zod#what-about-transforms

While the example is an extreme case where it switches from string to number, a more common one would be using .default which switches from T | undefined to just T.

So, inferring z.input would yield T | undefined while the output (post-parsing) is just T.

const usingDefault = z.string().default('example')
type zInput = z.input<typeof usingDefault> // should be string | undefined
type zOutput = z.output<typeof usingDefault> // should be string (z.infer is an alias for z.output)

from zod-to-json-schema.

StefanTerdell avatar StefanTerdell commented on May 23, 2024

Thanks!

I may have been eating crayons again, but I don't see how this is relevant when converting to a Json Schema as the output schema would depend on the implementation of the Json Schema parser.

For instance, Ajv will quietly ignore defaults unless the useDefaults flag is passed as true and will leave the property undefined if not. Like so:

const mySchema = z.object({
    myString: z.string().default("hello"),
  });

const jsonSchema = zodToJsonSchema(mySchema);

const ajvWithDefaults = new Ajv({ useDefaults: true });
const dataWithDefaults = {}
ajvWithDefaults.validate(jsonSchema, dataWithDefaults)
console.log(dataWithDefaults)
// outputs: { myString: "hello" }

const ajvWithoutDefaults = new Ajv();
const dataWithoutDefaults = {}
ajvWithoutDefaults.validate(jsonSchema, dataWithoutDefaults)
console.log(dataWithoutDefaults)
// outputs: { }

Zod marks fields within an object with defaults as optional both in input and output and only "secretly guarantees" a value in the end. Like so:

const mySchema = z.object({
  myString: z.string().default("hello"),
});

type input = z.input<typeof mySchema>;
// Compiles to:
// type input = {
//    myString?: string;
// }
type output = z.output<typeof mySchema>;
// Also compiles to:
// type output = {
//     myString?: string;
// }

const data = mySchema.parse({})
// data = {
//   myString: "hello"
// }

The example you're using is also a bit broken since both types are inferred to simply string. In zod^3.x.x, optional fields aren't unions with undefined anymore under the hood.

But I'm getting the feeling that I'm missing something here.. Would be open to a clearer issue or a PR of course, but I think I'll go ahead and close this issue in the meantime.

Thanks for reaching out!

from zod-to-json-schema.

FlorianWendelborn avatar FlorianWendelborn commented on May 23, 2024

Regarding your example, I think this may be different in the way you tested it. Perhaps a different TS version or no strict mode?

Here’s a repro for yielding two different input/output types from your example: TypeScript Playground

As you can see, the tooltip shows it as non-optional, as it should:
image

Here is the repro of my example, where you can also see it’s string | undefined vs string respectively:

TypeScript Playground

from zod-to-json-schema.

FlorianWendelborn avatar FlorianWendelborn commented on May 23, 2024

I don't see how this is relevant when converting to a Json Schema

As far as I’m concerned, at least for my particular use-cases so far, JSON Schemas are just an intermediary step to convert X -> JSON -> TypeScript Interfaces with X being OpenAPI or zod.

And I’d be surprised if the JSON schema for an optional property looks exactly the same as the JSON schema for a non-optional property. I don’t really want to use JSON schemas in the first place, but they’re a pretty widely-supported intermediary between different typed formats, so maybe my assumptions are somehow wrong. That’s also why I can’t provide the expected generated types, as I’ve never used JSON schemas for anything but converting it to something else.

Also, there’s still the other edge-case with transforms where the input type could be string while the output is number. That certainly has to be reflected in the schema (although I personally only care about the default/partial/undefined support as I don’t use other forms of transforms)

from zod-to-json-schema.

StefanTerdell avatar StefanTerdell commented on May 23, 2024

Would you look at that! Looks like I have some form of environmental issue.

Anyway, I took a look at it and it seems like z.output just uses the inferred return type from the transform function, so there's no actual runtime schema for the output. In other words: it can't be done with the current Zod implementation. Sorry :(

Maybe running https://www.npmjs.com/package/ts-json-schema-generator or something like it on the inferred type could work but I haven't given it a try.

from zod-to-json-schema.

StefanTerdell avatar StefanTerdell commented on May 23, 2024

What I would need is something like transformInto(nextSchema, func) that would pass the new schema down the chain. There's a PR here for something similiar, but looks like it's gone stale: colinhacks/zod#420

from zod-to-json-schema.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.