asteasolutions / zod-to-openapi

A library that generates OpenAPI (Swagger) docs from Zod schemas
MIT License
993 stars 60 forks source link

example expects z.infer but for parameters, it should be z.input #189

Closed svachalek closed 9 months ago

svachalek commented 1 year ago

If a parameter has a .default then an example is legal input as a param even if it doesn't supply the parameter. However this won't compile because example is declared using z.infer<...> like

openapi<T extends ZodTypeAny>(this: T, metadata: Partial<ZodOpenAPIMetadata<z.infer<T>>>): T;

If instead it used z.input<T> then it would compile. For example output however, this is correct, it should be z.output or z.infer which are equivalent. Possibly this needs a new exampleInput: field? I'm not sure of all the implications.

AGalabov commented 1 year ago

@svachalek thank you for using @asteasolutions/zod-to-openapi. I don't think I fully understand what the problem is. Would you be able to give me full code examples of what compiles and what doesn't. Thanks in advance

tionkje commented 10 months ago

After discovering today that next to z.infer there is also z.input and z.output. Where z.infer is the same as z.input. https://zod.dev/?id=type-inference

I ran to the exact issue @svachalek is talking about.

The example property of openapi is using the z.output or z.infer to get the type. But for input types (like api Input data) the z.input would be better.

Hereby a full code example that shows the issue

import { extendZodWithOpenApi } from '@asteasolutions/zod-to-openapi';
import { z } from 'zod';

extendZodWithOpenApi(z);

const example = {
  requiredField:'required'
};

z.object({
  optionalField:z.string().default('defaultValue'),
  requiredField:z.string()
}).openapi({example});
// Typescript errors here because of missing the optional field.

Would it work if the type of example is a union of z.input and z.output?

AGalabov commented 9 months ago

@tionkje I merged your PR but made the change to only use z.input as this is what we handle with the generation as well. It is now available as part of v6.4.0