CoolFace
Datasetpublic

enigmare/v2-crawler

sourceHugging Faceupdated 28d agoView on Hugging Face
1likes889downloads
zod.jsonl96 linesDownload Raw Back to stackoverflow
1{"id":"stack-71782572","source":"stackoverflow","questionId":71782572,"title":"How can I create a schema with Zod that validates that the value is using the type Schema?","tags":["typescript","zod"],"text":"Title: How can I create a schema with Zod that validates that the value is using the type Schema?\nTags: typescript, zod\nSource: Stack Overflow\n\nQuestion:\nI have an endpoint that should get a parameter `method` which should comply with the Axios type `Method`.\n\nHow can I create a schema with Zod that validates that the value is using the type `Schema`?\n\n```\nimport { Method } from 'axios';\n\nconst Schema = zod.object({\n method: zod.someHowUseTheTypeFrom(Method),\n});\n```\n\nThe type of `Method` from the Axios package is:\n\n```\nexport type Method =\n | 'get' | 'GET'\n | 'delete' | 'DELETE'\n | 'head' | 'HEAD'\n | 'options' | 'OPTIONS'\n | 'post' | 'POST'\n | 'put' | 'PUT'\n | 'patch' | 'PATCH'\n | 'purge' | 'PURGE'\n | 'link' | 'LINK'\n | 'unlink' | 'UNLINK'\n```\n\n========================================\n\nTop Answer:\nI have found out that using `z.custom()` is working for me, and would be appropriate for this kind of problem.\n\n[Edited]\nAccording to @esteban-toress, we still have to add a validation function at the end like this `z.custom((value) => //do something & return a boolean)`. Otherwise, just `z.custom()` only returns `ZodAny` type which allows `any` value.\n\n[Edited]\nThis solution is only preferable for type inferences if you wanted to use this to please Typescript types, but I would not recommend this for Zod validation due to the above behavior.\n\nSee docs:\nhttps://zod.dev/?id=custom-schemas\n\n========================================\n\nCode:\n```text\nimport { Method } from 'axios';\n\nconst Schema = zod.object({\n  method: zod.someHowUseTheTypeFrom(Method),\n});\n```\n\n```text\nexport type Method =\n  | 'get' | 'GET'\n  | 'delete' | 'DELETE'\n  | 'head' | 'HEAD'\n  | 'options' | 'OPTIONS'\n  | 'post' | 'POST'\n  | 'put' | 'PUT'\n  | 'patch' | 'PATCH'\n  | 'purge' | 'PURGE'\n  | 'link' | 'LINK'\n  | 'unlink' | 'UNLINK'\n```\n\n```text\nmethod\n```\n\n```text\nMethod\n```\n\n```text\nSchema\n```\n\n```text\nMethod\n```\n\n```js\nimport { z } from 'zod';\nimport type { Method } from 'axios';\n\nconst methods: z.ZodType<Method> = z.enum(['get', 'GET', ...]);\n```\n\n```js\nconst methods z.ZodType<Method> = z.enum(['get']);\n```\n\n```js\nimport { z } from \"zod\";\nimport { Method } from \"axios\";\n\nconst METHOD_MAP: { [K in Method]: null } = {\n  get: null,\n  GET: null,\n  delete: null,\n  DELETE: null,\n  head: null,\n  HEAD: null,\n  options: null,\n  OPTIONS: null,\n  post: null,\n  POST: null,\n  put: null,\n  PUT: null,\n  patch: null,\n  PATCH: null,\n  purge: null,\n  PURGE: null,\n  link: null,\n  LINK: null,\n  unlink: null,\n  UNLINK: null\n};\n\nconst METHODS = (Object.keys(METHOD_MAP) as unknown) as readonly [\n  Method,\n  ...Method[]\n];\nconst methods: z.ZodType<Method> = z.enum(METHODS);\n```\n\n```text\nMethod\n```\n\n```text\nMethod\n```\n\n```text\naxios\n```\n\n```text\nMethod\n```\n\n```text\nz.something(<type here>)\n```\n\n```text\nMethod\n```\n\n```text\naxios\n```\n\n```text\nmethods\n```\n\n```text\nenum\n```\n\n```text\n'get'\n```\n\n```text\n'get'\n```\n\n```text\nMethod\n```\n\n```text\nMethod\n```\n\n```text\naxios\n```\n\n```text\nMethod\n```\n\n```text\nMethod\n```\n\n```text\nMETHODS\n```\n\n```text\nMETHODS_MAP\n```\n\n```text\nMETHOD_MAP\n```\n\n```text\nMethod\n```\n\n```text\nMethod\n```\n\n```text\nconst methods = ['get','GET',...] as const;\n\nexport type Method = (typeof methods)[number];\n\nzod.enum(methods);\n```\n\n```text\ntypescript\n```\n\n```text\nzod\n```\n\n```text\nz.custom<ExistingType>()\n```\n\n```text\nz.custom<ExistingType>((value) => //do something & return a boolean)\n```\n\n```text\nz.custom<ExistingType>()\n```\n\n```text\nZodAny\n```\n\n```text\nany\n```\n\n```text\nexport type InferZodMap<T extends abstract new (...args: any) => any> = {\n    [k in keyof Partial<InstanceType<T>>]?: unknown;\n};\n\n\n// then use it like\n\ntype User {\n    email: string;\n}\n\nconst UserInsertValidation = z.object({\n  email: z.string(),\n} satisfies InferZodMap<User>);\n```\n\n```text\nenum MethodEnum {\n      'get', 'GET', 'post', 'POST', ...\n    }\n    \n    export type Method = keyof typeof MethodEnum // will export type 'get' | 'GET' | 'post' | 'POST' | ...\n    \n    const Schema = zod.object({\n      method: zod.nativeEnum(MethodEnum),\n    });\n```\n\n```text\nnativeEnum()\n```\n\n```js\nimport { Method } from \"axios\";\nimport { isLiteral, TypeGuard } from \"isguard-ts\";\n\nconst isMethod: TypeGuard<Method> = isLiteral(\n    \"DELETE\",\n    \"GET\",\n    \"HEAD\",\n    \"LINK\",\n    \"OPTIONS\",\n    \"PATCH\",\n    \"POST\",\n    \"PURGE\",\n    \"PUT\",\n    \"QUERY\",\n    \"UNLINK\",\n    \"delete\",\n    \"get\",\n    \"head\",\n    \"link\",\n    \"options\",\n    \"patch\",\n    \"post\",\n    \"purge\",\n    \"put\",\n    \"query\",\n    \"unlink\",\n);\n\nconst MethodSchema = isMethod.zod();\n```\n\n```js\nimport { Method } from \"axios\";\nimport { isLiteral, TypeGuard } from \"isguard-ts\";\n\n// ❌ TypeScript error - not all values were provided\nconst isMethodMissingValues: TypeGuard<Method> = isLiteral(\"GET\", \"POST\");\n\nconst MethodSchema = isMethod.zod();\n```\n\n```text\n.zod\n```\n\n========================================\n\nComments:\n- `zod.string().regex(&#47;^(get|delete|...)$&#47;)` was the best I could do with the documentation on the README\n- @kellys thanks. I also found `zod.enum(['get','GET',...])`, but I prefer to use the type directly\n- @Dotan, have you found a way to do this directly with existing types or maybe another way that doesn't require using a Zod method like `z.enum(...)`? Thanks.\n- That's cool but what I was going for is to use the Method type directly from axios, so that I don't have to repeat it, or at least I have typeScript verify that I use the correct type.\n- @Dotan I have a same thought. I though zod can reduce my time on calling request param type check, but now I fond out I have to do a repeated work, already done in typescript type defination, but in a zod way, to support runtime validation.\n- Thanks for the solution! Is there a reason why you are not skipping `METHODS` and use `z.nativeEnum` instead? In your example, can't you just do `z.nativeEnum(METHOD_MAP)`, assuming you also set a string value on each entry of the `METHOD_MAP`? Would need to change its type to `{ [K in Method]: K }` as well.\n- @Souperman Do you know how to export just an a array of string from a package you have control over wihtout bringing it all as dependancy ?\n- I'm not sure of your exact situation, but you may need to split the package into two parts if you don't want to include the entire package as a dependency. Depending on where you're running your code and how the code is transpiled, you may not need to worry too much about including an entire package just for a constants array since unused code may be dropped by the tree shaker. Hard to say more though without details. It might make sense for you to ask a new top level question.\n- @BennettDams No reason, your suggestion with `z.nativeEnum` looks like an improvement. I guess one reason to keep it is if you want a list of all methods for some reason, but if not then `nativeEnum` seems like less code and fewer type assertions.\n- Zod is an absolute joke. lol\n- While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes. - From Review\n- As it’s currently written, your answer is unclear. Please edit to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center.\n- This works but worth noticing that you will need to add a validation function at the end otherwise zod will allow any value zod.dev/?id=custom-schemas\n- best answer honestly\n- this is cool, didn't know this\n- I wouldn't recommend this anymore though. The quickest work around from that is to just copy and paste your typescript to this website transform.tools/typescript-to-zod and you will have your schema. Or even check this existing solution out: github.com/fabien0102/ts-to-zod\n- How would this work? `User` is a type, so how can you use `typeof User` here? Its not a value.\n- we are using satisfies aka the object should satisfies the type.\n- Yes, I understand, but `typeof User` you are saying `typeof `, which would give a *TS2693: User only refers to a type, but is being used as a value here.* kind of error right?\n- oh my bad you can just say User for my usecase User was coming from another class, i have updated the example\n- Really clever comment! Thank you!","metadata":{"transformedAt":"2026-08-18T18:33:48.864Z","totalAnswersIncluded":1,"totalCodeBlocksIncluded":44,"totalLines":356,"estimatedTokens":2079}}2{"id":"stack-75317224","source":"stackoverflow","questionId":75317224,"title":"How to validate a string literal type using zod","tags":["reactjs","typescript","zod"],"text":"Title: How to validate a string literal type using zod\nTags: reactjs, typescript, zod\nSource: Stack Overflow\n\nQuestion:\nI have this Type\n\n```\nexport type PaymentType = 'CHECK' | 'DIRECT DEPOSIT' | 'MONEY ORDER';\n```\n\nI want to validate this literal string type in zod. Currently, I have is as a string, but that wrong is not a string. I don't know what to put.\n\n```\nconst schema = z.object({\n paymentType: z.string() // I want to validate this field\n});\n```\n\nSo far, I have tried enums, strings, and objects. I cannot find the right answer.\n\n========================================\n\nTop Answer:\n@Millenial2020 I landed here looking for something else... and its a bit late...\n\nHowever here's an answer, including how to resolve the issue: *\"type 'string' is not assignable to type 'PaymentType'\"* that you mention in a comment to the other answer in this thread:\n\nTry using `as const`:\n\n```\n// note the 'as const'\nexport const PAYMENT_TYPES = ['CHECK', 'DIRECT DEPOSIT', 'MONEY ORDER'] as const\n\n// works great\nexport const zPaymentType = z.enum(PAYMENT_TYPES)\n\n// these types are all equivalent\nexport type PaymentType = 'CHECK' | 'DIRECT DEPOSIT' | 'MONEY ORDER'\nexport type PaymentType_TypeScript = (typeof PAYMENT_TYPES)[number]\nexport type PaymentType_Zod = z.infer\n```\n\nThis is called a *const assertion*, added in TypeScript 3.4: see release notes for this feature.\n\n`as const` tells TypeScript that your array definition is a literal readonly tuple and that extra piece of information is what enables you to work with it with type definitions + zod's `z.enum()`.\n\nWhen you define an array of strings and provide no other information, TypeScript infers a \"widened\" type that encompasses all of the values. If you think about it, it *has to* assume your array is of type `string[]` because you are free to manipulate the array and mutate its items to things that *aren't* one of 'CHECK', 'DIRECT DEPOSIT', or 'MONEY ORDER'.\n\nThe other answer suggests using `enum` however you can search out articles on why TypeScript enums are \"dangerous\" or \"broken\". The `as const` approach delivers a similar capability to enums in a more type-safe way... which also helps explain why a leading run-time type-checking library like zod chose to call *this approach* its official `enum` type instead of the one built into the language (which you can use with `z.nativeEnum()`).\n\n========================================\n\nCode:\n```text\nexport type PaymentType = 'CHECK' | 'DIRECT DEPOSIT' | 'MONEY ORDER';\n```\n\n```text\nconst schema = z.object({\n    paymentType: z.string() // I want to validate this field\n});\n```\n\n```text\nimport { z } from 'zod';\nconst PaymentTypeSchema = z.union([\n  z.literal('CHECK'),\n  z.literal('DIRECT DEPOSIT'),\n  z.literal('MONEY ORDER'),\n]);\ntype PaymentType = z.infer<typeof PaymentTypeSchema>;\n\nconst schema = z.object({\n  paymentType: PaymentTypeSchema,\n});\n```\n\n```text\nconst PaymentTypeSchema = z.enum([\"CHECK\", \"DIRECT DEPOSIT\", \"MONEY ORDER\"]);\nconst schema = z.object({\n  paymentType: PaymentTypeSchema,\n});\n```\n\n```text\nenum PaymentType {\n  Check = 'CHECK',\n  DirectDeposit = 'DIRECT DEPOSIT',\n  MoneyOrder = 'MONEY ORDER'\n}\n\nconst PaymentTypeSchema = z.nativeEnum(PaymentType);\nconst schema = z.object({\n  paymentType: PaymentTypeSchema,\n});\n```\n\n```text\nz.literal\n```\n\n```text\nz.enum\n```\n\n```text\nPaymentType\n```\n\n```text\nz.nativeEnum\n```\n\n```text\n// note the 'as const'\nexport const PAYMENT_TYPES = ['CHECK', 'DIRECT DEPOSIT', 'MONEY ORDER'] as const\n\n// works great\nexport const zPaymentType = z.enum(PAYMENT_TYPES)\n\n// these types are all equivalent\nexport type PaymentType = 'CHECK' | 'DIRECT DEPOSIT' | 'MONEY ORDER'\nexport type PaymentType_TypeScript = (typeof PAYMENT_TYPES)[number]\nexport type PaymentType_Zod = z.infer<typeof zPaymentType>\n```\n\n```text\nas const\n```\n\n```text\nas const\n```\n\n```text\nz.enum()\n```\n\n```text\nstring[]\n```\n\n```text\nenum\n```\n\n```text\nas const\n```\n\n```text\nenum\n```\n\n```text\nz.nativeEnum()\n```\n\n```text\nconst schema = z.object({\n    priority: 'low' | 'medium' | 'high',\n})\n```\n\n```text\nconst schema = z.object({\n    priority: z.enum(['low', 'medium', 'high']),\n})\n```\n\n```text\nexport type ProductCode = 'PROD-A' | 'PROD-B'\n```\n\n```text\nexport const ProductCodesSchema = ['PROD-A', 'PROD-B'] as const;\n\nexport type ProductCode = (typeof ProductCodesSchema)[number];\n```\n\n```text\nexport const GetPriceRequestSchema = z.object({\n  product: z.enum(ProductCodesSchema),\n  priceCode: z.number(),\n});\n\nexport const getPriceForProduct = async (product: ProductCode, priceCode: number) => {\n}\n```\n\n```text\nimport { z } from 'zod';\nconst PaymentTypeSchema = z.literal([\n  'CHECK',\n  'DIRECT DEPOSIT',\n  'MONEY ORDER',\n]);\ntype PaymentType = z.infer<typeof PaymentTypeSchema>; // 'CHECK' | 'DIRECT DEPOSIT' | 'MONEY ORDER'\n```\n\n```js\nimport { z } from 'zod';\nconst PaymentTypeSchema = z.enum([\n   'CHECK',\n   'DIRECT DEPOSIT',\n   'MONEY ORDER', \n]);\ntype PaymentType = z.infer<typeof PaymentTypeSchema>; // 'CHECK' | 'DIRECT DEPOSIT' | 'MONEY ORDER'\n```\n\n```text\n.literal\n```\n\n```text\n.enum\n```\n\n```text\n.enum\n```\n\n========================================\n\nComments:\n- What does this have to do with React?\n- They don't work for me I get this error.Types of property 'paymentType' are incompatible. Type 'string' is not assignable to type 'PaymentType'. you can test this by setting a useState that takes PaymentType as a value.\n- It's difficult for me to respond to your problem without specific code, perhaps you could update your question to show the exact code you have that's giving you an error? It sounds to me like you are calling the `setState` function from your `useState` hook with something that you haven't refined down to the `PaymentType` value. For example if you have a regular `input` element you cannot call `setState` with the `e.target.value` directly because that will be a string.","metadata":{"transformedAt":"2026-08-18T18:33:48.864Z","totalAnswersIncluded":1,"totalCodeBlocksIncluded":28,"totalLines":229,"estimatedTokens":1464}}3{"id":"stack-75157299","source":"stackoverflow","questionId":75157299,"title":"How can zod date type accept ISO date strings?","tags":["node.js","typescript","date","zod"],"text":"Title: How can zod date type accept ISO date strings?\nTags: node.js, typescript, date, zod\nSource: Stack Overflow\n\nQuestion:\nWhen defining a schema with zod, how do I use a date type?\n\nIf I use `z.date()` (see below) the date object is serialized to a ISO date string. But then if I try to parse it back with zod, the validator fails because a string is not a date.\n\n```\nimport { z } from \"zod\"\n\nconst someTypeSchema = z.object({\n t: z.date(),\n})\ntype SomeType = z.infer\n\nfunction main() {\n const obj1: SomeType = {\n t: new Date(),\n }\n const stringified = JSON.stringify(obj1)\n console.log(stringified)\n const parsed = JSON.parse(stringified)\n const validated = someTypeSchema.parse(parsed) // <- Throws error! \"Expected date, received string\"\n console.log(validated.t)\n}\nmain()\n```\n\n========================================\n\nTop Answer:\nI used this from the README which works since v3.20 https://github.com/colinhacks/zod#dates\n\nIn your code snippet it would turn into this:\n\n```\nimport { z } from \"zod\"\n\nconst someTypeSchema = z.object({\n t: z.coerce.date(),\n})\ntype SomeType = z.infer\n```\n\n========================================\n\nCode:\n```text\nimport { z } from \"zod\"\n\nconst someTypeSchema = z.object({\n    t: z.date(),\n})\ntype SomeType = z.infer<typeof someTypeSchema>\n\nfunction main() {\n    const obj1: SomeType = {\n        t: new Date(),\n    }\n    const stringified = JSON.stringify(obj1)\n    console.log(stringified)\n    const parsed = JSON.parse(stringified)\n    const validated = someTypeSchema.parse(parsed) // <- Throws error! \"Expected date, received string\"\n    console.log(validated.t)\n}\nmain()\n```\n\n```text\nz.date()\n```\n\n```text\nimport { z } from \"zod\"\n\nconst someTypeSchema = z.object({\n    t: z.string().transform((str) => new Date(str)),\n})\ntype SomeType = z.infer<typeof someTypeSchema>\n\nfunction main() {\n    const obj1: SomeType = {\n        t: new Date(),\n    }\n    const stringified = JSON.stringify(obj1)\n    console.log(stringified) // <-- {\"t\":\"2023-09-07T07:19:51.128Z\"}\n    const parsed = JSON.parse(stringified)\n    const validated = someTypeSchema.parse(parsed)\n    console.log(validated.t instanceof Date) // <-- \"true\"\n}\nmain()\n```\n\n```text\ntransform\n```\n\n```text\nDate\n```\n\n```text\nconst someTypeSchema = z.object({\n    t: z.string().refine((arg) =>\n      arg.match(\n        /^(\\d{4})-(\\d{2})-(\\d{2})T(\\d{2}):(\\d{2}):(\\d{2}(?:\\.\\d*)?)((-(\\d{2}):(\\d{2})|Z)?)$/\n    ))\n})\n```\n\n```text\nimport { z } from \"zod\"\n\nconst someTypeSchema = z.object({\n    t: z.coerce.date(),\n})\ntype SomeType = z.infer<typeof someTypeSchema>\n```\n\n```js\ndate: z.coerce.date();\n```\n\n```js\ndate: z.string().pipe(z.coerce.date())\n```\n\n```text\n^zod 3.20\n```\n\n```text\nzod 3.20\n```\n\n```text\nconst BirthAtZod = z\n  .string()\n  .min(1, { message: 'mandatory' })\n  // changes DD-MM-YYYY to YYYY-MM-DD\n  .transform((v) => v.split('-').reverse().join('-'))\n  // changes YYYY-MM-DD to YYYY-MM-DDT00:00:00.000Z\n  .transform((v) => `${v}T00:00:00.000Z`)\n  .pipe(\n    z\n      .string()\n      .datetime({ message: 'incorrect format' }),\n  );\n\nconst good = BirthAtZod.safeParse('20-10-2023');\nif (good.success) {\n  console.log(result.data) // 2023-10-20T00:00:00.000Z\n}\n\nconst bad = BirthAtZod.safeParse('29-02-2023');\nif (!bad.success) {\n  console.error(bad.error.format()) // { _errors: ['incorrect format'] }\n}\n```\n\n```text\nYYYY-MM-DDTHH:mm:ss.sssZ\n```\n\n```js\nz.iso.date()\n```\n\n========================================\n\nComments:\n- I found `z.string().datetime()` to work for me: github.com/colinhacks/zod#iso-datetimes\n- @KevinAshworth but your inferred type will then have a string property, right? Not a Date. But yes the **validation** will catch an a string that isn't a ISO date.\n- Yup. In my case, I'm dealing with date strings sent as strings from an API endpoint.\n- but I want the property to be a `Date`. I found the answer, I can use `transform` to convert string to `Date` when parsing.\n- you can do the same with `coerce` from string to date with `z.string().pipe(z.coerce.date())`","metadata":{"transformedAt":"2026-08-18T18:33:48.864Z","totalAnswersIncluded":1,"totalCodeBlocksIncluded":14,"totalLines":178,"estimatedTokens":997}}4{"id":"stack-71477015","source":"stackoverflow","questionId":71477015,"title":"Specify a Zod schema with a non-optional but possibly undefined field","tags":["typescript","zod"],"text":"Title: Specify a Zod schema with a non-optional but possibly undefined field\nTags: typescript, zod\nSource: Stack Overflow\n\nQuestion:\nIs it possible to define a Zod schema with a field that is possibly `undefined`, but non-optional. In TypeScript this is the difference between:\n\n```\ninterface IFoo1 {\n somefield: string | undefined;\n}\n\ninterface IFoo2 {\n somefield?: string | undefined;\n}\n\nconst schema = z.object({\n somefield: z.union([z.string(), z.undefined()]),\n}); // Results in something like IFoo2\n```\n\nAs far as I can tell using `z.union([z.string(), z.undefined()])` or `z.string().optional()` results in the field being equivalent to `IFoo2`.\n\nI'm wondering if there is a way to specify a schema that behaves like `IFoo1`.\n\n### Context / Justification\n\nThe reason that I might want to do something like this is to force developers to think about whether or not the field should be `undefined`. When the field is optional, it can be missed by accident when constructing objects of that type. A concrete example might be something like:\n\n```\ninterface IConfig {\n name: string;\n emailPreference: boolean | undefined;\n}\nenum EmailSetting {\n ALL,\n CORE_ONLY,\n}\n\nfunction internal(config: IConfig) {\n return {\n name: config.name,\n marketingEmail: config.emailPreference ? EmailSetting.ALL : EmailSetting.CORE_ONLY,\n }\n}\n\nexport function signup(userName: string) {\n post(internal({ name: userName }));\n}\n```\n\nThis is sort of a contrived example, but this occurs a lot in our codebase with React props. The idea with allowing the value to be `undefined` but not optional is to force callers to specify that, for example, there was no preference specified vs picking yes or no. In the example I want an error when calling `internal` because I want the caller to think about the email preference. Ideally the type error here would lead me to realize that I should ask for email preference as a parameter to `signup`.\n\n========================================\n\nTop Answer:\nBuilding off the answer from Gus Bus... If you want every property to be required (non-optional), I made a utility function to make this a little easier.\n\n```\nexport type Full = { [K in keyof T]-?: [T[K]] } extends infer U\n ? U extends Record\n ? { [K in keyof U]: U[K][0] }\n : never\n : never;\n\n/** Marks every property as required (non-optional). However property values can still be undefined. */\nexport function full(x: T) {\n return x as Full;\n}\n```\n\nUsage:\n\n```\nconst schema = z\n .object({\n name: z.string().optional(),\n })\n .transform(full);\n```\n\nBefore (no transform):\n\nhttps://i.sstatic.net/RSy4S.png\n\nAfter (transform):\n\nhttps://i.sstatic.net/42Q9g.png\n\nReference:\nhttps://stackoverflow.com/a/57334147/704532\n\n========================================\n\nCode:\n```js\ninterface IFoo1 {\n  somefield: string | undefined;\n}\n\ninterface IFoo2 {\n  somefield?: string | undefined;\n}\n\nconst schema = z.object({\n  somefield: z.union([z.string(), z.undefined()]),\n}); // Results in something like IFoo2\n```\n\n```js\ninterface IConfig {\n  name: string;\n  emailPreference: boolean | undefined;\n}\nenum EmailSetting {\n  ALL,\n  CORE_ONLY,\n}\n\nfunction internal(config: IConfig) {\n  return {\n    name: config.name,\n    marketingEmail: config.emailPreference ? EmailSetting.ALL : EmailSetting.CORE_ONLY,\n  }\n}\n\nexport function signup(userName: string) {\n  post(internal({ name: userName }));\n}\n```\n\n```text\nundefined\n```\n\n```text\nz.union([z.string(), z.undefined()])\n```\n\n```text\nz.string().optional()\n```\n\n```text\nIFoo2\n```\n\n```text\nIFoo1\n```\n\n```text\nundefined\n```\n\n```text\nundefined\n```\n\n```text\ninternal\n```\n\n```text\nsignup\n```\n\n```text\nconst schema = z\n    .object({\n        somefield: z.string().optional(),\n    })\n    .transform((o) => ({ somefield: o.somefield }));\n\ntype IFoo1 = z.infer<typeof schema>;\n// is equal to { somefield: string | undefined }\n```\n\n```text\ntransform\n```\n\n```text\nconst schema = z.optional(z.string());\n\nschema.parse(undefined); // => returns undefined\ntype A = z.infer<typeof schema>; // string | undefined\n```\n\n```text\nz.optional()\n```\n\n```text\nexport type Full<T> = { [K in keyof T]-?: [T[K]] } extends infer U\n  ? U extends Record<keyof U, [any]>\n    ? { [K in keyof U]: U[K][0] }\n    : never\n  : never;\n\n/** Marks every property as required (non-optional). However property values can still be undefined. */\nexport function full<T>(x: T) {\n  return x as Full<T>;\n}\n```\n\n```text\nconst schema = z\n  .object({\n    name: z.string().optional(),\n  })\n  .transform(full);\n```\n\n```js\nconst fooSchema = z.custom<{\n  somefield: string | undefined;\n}>()\n\nfooSchema.parse({}) // fails\nfooSchema.parse({somefield: undefined}) // succeeds\n```\n\n```text\nz.custom<yourType>()\n```\n\n========================================\n\nComments:\n- Have you considered using `null` instead of `undefined`? I think it'd be also more explicit as these two values were made to distinguish between a variable not being set/initialised yet (`undefined`) and a variable currently without a specific value (`null`).\n- That’s a reasonable suggestion, and probably what I’ll do if there’s no work around, but for my specific use case I was hoping to use `undefined` to represent the absence of a configuration where `null` is a possible configuration. If I pass `null` in to mean “no preference” as well as a possible “preference is `null`“ then there’s a bit of overloading going on. I suppose I could use a bonafide optional type but I was hoping to simply use `undefined`\n- OP is not asking how to make a schema accept `undefined`. The question is whether there \"*is a way to specify a schema that behaves like `IFoo1`*\", specifically with its `somefield` property being present but `undefined`.\n- @Souperman I know this is old, but would it have solved your problem?\n- Really wish I could figure out how to create a reusable function to do this. Or that Zod had something like .undefinable() and not just .optional()\n- This looks like it's only half of the solution because it's only handling the type inference side of things. You need to make sure that when you parse the object that the fields are being set.\n- I think you're right. But wouldn't your original answer have the same issue? I'm still working on this. I think the validation needs to check that the entire object has certain keys, and not necessarily do prop validation to find missing props.\n- I will try this tomorrow, and if it works I'll update the answer. stackoverflow.com/questions/77958464/&hellip;\n- The solution in my original post would convert an empty object to an object with `{blah: undefined}`. Your solution would leave it as empty, all you're doing is type casting. Which is fine if that's what you want - I was just pointing out there is a material difference between the two solutions.\n- Thanks. In my use case, I'm wanting to warn developers that they forgot to include a key.\n- I haven't been able to figure it out, and I have to pause on this for now. Thanks.\n- I believe this could be properly solved if Zod ever supports TypeScript's --exactOptionalPropertyTypes flag. github.com/colinhacks/zod/issues/635\n- From the documentation: \"*If you don't provide a validation function, Zod will allow any value. This can be dangerous!*\" So your example does not actually work. (At best, it might not typecheck.)","metadata":{"transformedAt":"2026-08-18T18:33:48.865Z","totalAnswersIncluded":1,"totalCodeBlocksIncluded":19,"totalLines":243,"estimatedTokens":1813}}5{"id":"stack-73825273","source":"stackoverflow","questionId":73825273,"title":"Creating a zod enum from an object","tags":["typescript","validation","object","types","zod"],"text":"Title: Creating a zod enum from an object\nTags: typescript, validation, object, types, zod\nSource: Stack Overflow\n\nQuestion:\nI have this **object**:\n\n```\nconst properties = [\n { value: \"entire_place\", label: \"The entire place\" },\n { value: \"private_room\", label: \"A private room\" },\n { value: \"shared_room\", label: \"A shared room\" },\n] as const;\n```\n\nI need to use it with zod in order to\n\n- **Validate** and parse my data on the backend\n\n- Create a **typescript union type** with those possible values `\"entire_place\" | \"shared_room\" | \"private_room\"`\n\nAccording to the **zod documentation**, i can do this:\n\n```\nconst properties = [\n { value: \"entire_place\", label: \"The entire place\" },\n { value: \"private_room\", label: \"A private room\" },\n { value: \"shared_room\", label: \"A shared room\" },\n] as const;\n\nconst VALUES = [\"entire_place\", \"private_room\", \"shared_room\"] as const;\nconst Property = z.enum(VALUES);\ntype Property = z.infer;\n```\n\nHowever, I don't want to define my data **twice**, **one time with a label** (the label is used for ui purposes), and another without a **label**.\n\nI want to define it only once using the `properties` object, without the `VALUES` array, and use it to create a zod object and infer the type from the zod object.\n\nAny solutions how?\n\n========================================\n\nTop Answer:\nI took the example of the @Ruslan and @Souperman and create a simplified version\n\nMy propose is to wrap the z.enum function with `z_enumFromArray`\n\n```\nimport { z } from 'zod'\n\nfunction z_enumFromArray(array: string[]){\n return z.enum([array[0], ...array.slice(1)])\n}\n```\n\nExamples\n\n```\n// example of user19910212\nconst properties = [\n { value: \"entire_place\", label: \"The entire place\" },\n { value: \"private_room\", label: \"A private room\" },\n { value: \"shared_room\", label: \"A shared room\" },\n] as const;\nconst propertySchema = z_enumFromArray(properties.map(prop=>prop.value))\npropertySchema.parse(\"entire_place\") // pass\npropertySchema.parse(\"invalid_value\") // throws error\n\n// Another example using an Object as input\nconst status = {\n active: \"B0A47BD3-5CC2-49EF-BA69-9BC881A2B6C2\",\n inactive: \"BDABF381-FA76-4578-81EC-FF3E56055A9E\",\n pending: \"2B517D1B-1710-41A6-B946-7AE2B93C7DDE\",\n} as const\nconst statusSchema = z_enumFromArray(Object.keys(status))\nstatusSchema.parse(\"active\") // pass\nstatusSchema.parse(\"invalid_value\") // throws error\n```\n\n========================================\n\nCode:\n```text\nconst properties = [\n  { value: \"entire_place\", label: \"The entire place\" },\n  { value: \"private_room\", label: \"A private room\" },\n  { value: \"shared_room\", label: \"A shared room\" },\n] as const;\n```\n\n```text\nconst properties = [\n  { value: \"entire_place\", label: \"The entire place\" },\n  { value: \"private_room\", label: \"A private room\" },\n  { value: \"shared_room\", label: \"A shared room\" },\n] as const;\n\nconst VALUES = [\"entire_place\", \"private_room\", \"shared_room\"] as const;\nconst Property = z.enum(VALUES);\ntype Property = z.infer<typeof Property>;\n```\n\n```text\n\"entire_place\" | \"shared_room\" | \"private_room\"\n```\n\n```text\nproperties\n```\n\n```text\nVALUES\n```\n\n```text\nimport { z } from \"zod\";\n\nconst properties = [\n  { value: \"entire_place\", label: \"The entire place\" },\n  { value: \"private_room\", label: \"A private room\" },\n  { value: \"shared_room\", label: \"A shared room\" }\n] as const;\n\ntype Property = typeof properties[number][\"value\"];\n// z.enum expects a non-empty array so to work around that\n// we pull the first value out explicitly\nconst VALUES: [Property, ...Property[]] = [\n  properties[0].value,\n  // And then merge in the remaining values from `properties`\n  ...properties.slice(1).map((p) => p.value)\n];\nconst Property = z.enum(VALUES);\n```\n\n```text\nProperty\n```\n\n```text\nproperties\n```\n\n```text\n/**\n * `extractValuesAsTuple` extracts the values from a given enum-like object and returns them\n * in a tuple format.\n *\n * This helper is useful when working with libraries or utilities that expect a non-empty tuple\n * of string values, particularly when those utilities cannot accept a simple string array.\n *\n * @template T - The type of the enum-like object. It should be a record of string keys to string values.\n *\n * @param {T} obj - The enum-like object from which values should be extracted.\n *\n * @returns {[T[keyof T], ...T[keyof T][]]} - A tuple containing all the values from the given object.\n * The tuple is guaranteed to have at least one value.\n *\n * @example\n * const Colors = { RED: 'Red', GREEN: 'Green', BLUE: 'Blue' } as const;\n * const colorValues = extractValuesAsTuple(Colors); // ['Red', 'Green', 'Blue']\n *\n * @throws {Error} - Throws an error if the provided object is empty.\n */\nfunction extractValuesAsTuple<T extends Record<string, any>>(\n  obj: T\n): [T[keyof T], ...T[keyof T][]] {\n  const values = Object.values(obj) as T[keyof T][];\n  if (values.length === 0)\n    throw new Error('Object must have at least one value.');\n\n  // Explicitly extract the first value\n  const result: [T[keyof T], ...T[keyof T][]] = [values[0], ...values.slice(1)];\n\n  return result;\n}\nconst properties = [\n  { value: \"entire_place\", label: \"The entire place\" },\n  { value: \"private_room\", label: \"A private room\" },\n  { value: \"shared_room\", label: \"A shared room\" },\n] as const;\n\n// Extracting the 'value' properties into a tuple using the helper function\nconst propertyValues = extractValuesAsTuple(properties.map(p => p.value));\n\nconsole.log(propertyValues); // [\"entire_place\", \"private_room\", \"shared_room\"]\n```\n\n```js\nimport { z } from 'zod'\n\nfunction z_enumFromArray(array: string[]){\n  return z.enum([array[0], ...array.slice(1)])\n}\n```\n\n```text\n// example of user19910212\nconst properties = [\n  { value: \"entire_place\", label: \"The entire place\" },\n  { value: \"private_room\", label: \"A private room\" },\n  { value: \"shared_room\", label: \"A shared room\" },\n] as const;\nconst propertySchema = z_enumFromArray(properties.map(prop=>prop.value))\npropertySchema.parse(\"entire_place\") // pass\npropertySchema.parse(\"invalid_value\") // throws error\n\n\n// Another example using an Object as input\nconst status = {\n  active: \"B0A47BD3-5CC2-49EF-BA69-9BC881A2B6C2\",\n  inactive: \"BDABF381-FA76-4578-81EC-FF3E56055A9E\",\n  pending: \"2B517D1B-1710-41A6-B946-7AE2B93C7DDE\",\n} as const\nconst statusSchema = z_enumFromArray(Object.keys(status))\nstatusSchema.parse(\"active\") // pass\nstatusSchema.parse(\"invalid_value\") // throws error\n```\n\n```text\nz_enumFromArray\n```\n\n```js\nfunction convertConstToZodEnum<T extends Readonly<Record<string, string>>>(\n  obj: T,\n): z.ZodEnum<[T[keyof T], ...T[keyof T][]]> {\n  const values = Object.values(obj) as [T[keyof T], ...T[keyof T][]];\n  return z.enum([values[0], ...values.slice(1)]);\n}\n\nexport const TOPIC = {\n  uncategorized: \"uncategorized\",\n  tech: \"tech\",\n  lifestyle: \"lifestyle\",\n  programming: \"programming\",\n  typescript: \"typescript\",\n  react: \"react\",\n  wordpress: \"wordpress\",\n  nextjs: \"nextjs\",\n  python: \"python\",\n  vuejs: \"vuejs\",\n} as const;\n\nexport type TopicT = (typeof TOPIC)[keyof typeof TOPIC];\n\nexport const TOPIC_ZOD_ENUM = convertConstToZodEnum(TOPIC);\n\n// Use it as default value\nconst form = useForm({\n    defaultValues: {\n      topic: [TOPIC_ZOD_ENUM.parse(TOPIC_ZOD_ENUM.Enum.uncategorized)],\n    },\n});\n\n// Iteration example\nconst Component = () => (\n<select\n  onChange={(e) => {            \n    field.handleChange(Array.from(e.target.selectedOptions).map((option) => \n      option.value as TopicT)\n    );\n  }\n  multiple\n>\n  {Object.values(TOPIC).map((topic) => (\n    <option key={topic} value={topic}>\n      {topic}\n    </option>\n  ))}\n</select>\n);\n```\n\n```text\nas const\n```\n\n```text\nas const\n```\n\n```text\nEnum\n```\n\n```text\nas const\n```\n\n```text\nzod\n```\n\n```text\nas const\n```\n\n```text\nconvertConstToZodEnum\n```\n\n```text\nconst EventCodes = {\n  FirstEvent: \"FirstEvent\",\n} as const;\nexport type EventCode = (typeof EventCodes)[keyof typeof EventCodes];\n\nconst EventSchema = z.object({\n  // the magic bit is the type guard here:\n  code: z.string().refine((code): code is EventCode => {\n    return Object.values(EventCodes).includes(code as EventCode);\n  }),\n```\n\n```text\nas const\n```\n\n```text\nrefine()\n```\n\n========================================\n\nComments:\n- It works! Thank you. But is it possible that I pass the type to zod and zod automatically creates the enum from the possible values of the type?\n- Types don't exist at runtime. All of the type annotations that typescript uses to give you compiler checks will be stripped out and you'll just be left with Javascript. For `zod` to be able to do checks, it needs to have real world values. It's more of a TypeScript issue than a `zod` one. The type system lets you manipulate the types of runtime values with `typeof`, but you can't go in the other direction and manipulate runtime values with types.","metadata":{"transformedAt":"2026-08-18T18:33:48.865Z","totalAnswersIncluded":1,"totalCodeBlocksIncluded":23,"totalLines":328,"estimatedTokens":2195}}6{"id":"stack-74907523","source":"stackoverflow","questionId":74907523,"title":"Creating zod schema for generic interface","tags":["typescript","runtime","zod"],"text":"Title: Creating zod schema for generic interface\nTags: typescript, runtime, zod\nSource: Stack Overflow\n\nQuestion:\nI've got this generic interface for paginated response:\n\n```\nexport interface PaginatedResponse {\n pageIndex: number;\n pageSize: number;\n totalCount: number;\n totalPages: number;\n items: Array;\n}\n```\n\nAnd then I want to turn it in zod schema for runtime type checks.\nThe approach was like this:\n\n```\nconst PaginatedResponseSchema = z.object({\n pageIndex: z.number(),\n pageSize: z.number(),\n totalCount: z.number(),\n totalPages: z.number(),\n items: z.array(???), // = z.infer;\n```\n\nWhat type of array should be items in the schema?\n\n========================================\n\nCode:\n```text\nexport interface PaginatedResponse<T> {\n  pageIndex: number;\n  pageSize: number;\n  totalCount: number;\n  totalPages: number;\n  items: Array<T>;\n}\n```\n\n```text\nconst PaginatedResponseSchema = z.object({\n  pageIndex: z.number(),\n  pageSize: z.number(),\n  totalCount: z.number(),\n  totalPages: z.number(),\n  items: z.array(???), // <=\n});\n\nexport type PaginatedResponse<T> = z.infer<typeof PaginatedResponseSchema>;\n```\n\n```js\nfunction createPaginatedResponseSchema<ItemType extends z.ZodTypeAny>(\n  itemSchema: ItemType,\n) {\n  return z.object({\n    pageIndex: z.number(),\n    pageSize: z.number(),\n    totalCount: z.number(),\n    totalPages: z.number(),\n    items: z.array(itemSchema),\n  });\n}\n```\n\n```text\nitems\n```\n\n```text\nzod\n```\n\n========================================\n\nComments:\n- Fun fact: I was trying to do the exact same thing as you when I came to this google result.\n- i am also, looking for the same thing ; )\n- Is it also possible, to then create a type, using infer, with that createSchema function?\n- Should be `const schema = createPaginatedResponseSchema(z.string())` and then `type Schema = z.infer`","metadata":{"transformedAt":"2026-08-18T18:33:48.865Z","totalAnswersIncluded":0,"totalCodeBlocksIncluded":5,"totalLines":85,"estimatedTokens":455}}7{"id":"stack-73582246","source":"stackoverflow","questionId":73582246,"title":"Zod Schema: How to make a field optional OR have a minimum string contraint?","tags":["javascript","typescript","schema","zod"],"text":"Title: Zod Schema: How to make a field optional OR have a minimum string contraint?\nTags: javascript, typescript, schema, zod\nSource: Stack Overflow\n\nQuestion:\nI have a field where I want the value to either be optional OR have the field have a minimum length of `4`.\n\nI've tried the following:\n\n```\nexport const SocialsSchema = z.object({\n myField: z.optional(z.string().min(4, \"Please enter a valid value\")),\n});\n```\n\nThis passes if I used a value like: `\"good\"`, but if I've got an empty value then it fails.\n\nHow do I correctly implement a constraint using zod schemas to make an optional value with a minimum constraint if the value is not empty?\n\nIs it possible to do this without using regex or a regex solution the only way?\n\n========================================\n\nTop Answer:\nBased on this Github issue and it's answer\n\nUse the `or`-option in-combined with optional & literal, like this.\n\n```\nexport const SocialsSchema = z.object({\n myField: z\n .string()\n .min(4, \"Please enter a valid value\")\n .optional()\n .or(z.literal('')),\n});\n```\n\n========================================\n\nCode:\n```text\nexport const SocialsSchema = z.object({\n  myField: z.optional(z.string().min(4, \"Please enter a valid value\")),\n});\n```\n\n```text\n4\n```\n\n```text\n\"good\"\n```\n\n```text\nimport { z } from \"zod\";\nimport { strict as assert } from \"node:assert\";\n\n// `myString` is a string that can be either optional (undefined or missing),\n// empty, or min 4\nconst myString = z\n  .union([z.string().length(0), z.string().min(4)])\n  .optional()\n  .transform(e => e === \"\" ? undefined : e);\n\nconst schema = z.object({ test: myString });\n\nassert( schema.parse({}).test === undefined ); // missing string\nassert( schema.parse({ test: undefined }).test === undefined ); // string is undefined\nassert( schema.parse({ test: \"\" }).test === undefined ); // string is empty\nassert( schema.parse({ test: \"1234\" }).test === \"1234\" ); // string is min 4\n\n// these successfully fail\nassert( schema.safeParse({ test: \"123\" }).success !== true );\nassert( schema.safeParse({ test: 3.14 }).success !== true );\n```\n\n```text\n\"\"\n```\n\n```text\nundefined\n```\n\n```js\nimport { z } from \"zod\";\n\nexport const SocialsSchema = z.object({\n  myField: z.string().min(4, \"Please enter a valid value\").optional()\n});\n// ok\nconsole.log(SocialsSchema.parse({ myField: undefined }));\n\n// ok\nconsole.log(SocialsSchema.parse({ myField: \"1234\" }));\n\n// ok\nconsole.log(SocialsSchema.parse({ myField: \"\" }));\n\n// throws min error\nconsole.log(SocialsSchema.parse({ myField: \"123\" }));\n```\n\n```text\nexport const SocialsSchema = z.object({\n  myField: z\n    .string()\n    .min(4, \"Please enter a valid value\")\n    .optional()\n    .or(z.literal('')),\n});\n```\n\n```text\nor\n```\n\n```text\nimport { z } from \"zod\";\n\n// `myString` is a string that can be either optional (undefined or missing),\n// empty, or min 4\nconst myString = z\n  .union([z.string().min(4), z.string().length(0)])\n  .optional()\n  .transform(e => e === \"\" ? undefined : e);\n```\n\n```text\nz.string().length(0)\n```\n\n```text\nz.string().min(4)\n```\n\n```js\nimport { z } from \"zod\";\n\nfunction optional<T extends z.ZodTypeAny>(schema: T) {\n    return z\n        .union([schema, z.literal(\"\")])\n        .transform((value) => (value === \"\" ? undefined : value))\n        .optional();\n}\n\nconst myString = optional(z.string().min(4));\ntype MyString = z.infer<typeof myString>; // string | undefined\n```\n\n```text\nundefined\n```\n\n```js\nconst mySchema = z.object({\n  myField: z.string().min(4, \"Please enter a valid value\").nullish(),\n});\n```\n\n```js\n// zod schema\nz.object({\n    // valid if string or:\n    optional: z.string().optional(), // field not provided, or explicitly `undefined`\n    nullable: z.string().nullable(), // field explicitly `null`\n    nullish: z.string().nullish(), // field not provided, explicitly `null`, or explicitly `undefined`\n});\n\n// type\n{\n    optional?: string | undefined;\n    nullable: string | null;\n    nullish?: string | null | undefined;\n}\n```\n\n========================================\n\nComments:\n- It's not working for me for some reason. If my field is empty it still fails.\n- Working for me on stackblitz using the latest zod version\n- Weird, must be something else in my implementation affecting it, I'm resorting to using the following regex to solve the issue: `&#47;^(\\S{4,})?$&#47;` thanks for the help though, I'm sure your solution is correct in normal contexts!\n- I had the exact same issue, did you ever find a solution apart from the regex?\n- Nah we actually just decide to fully move away from using zod schemas because of issues like this...\n- @CamParry See if the answer I just posted can help you.\n- Nice! Not sure why mine wasn't working for them. It seemed fine on StackBlitz based on my code snippet above but maybe I didn't read the spec well enough.\n- @RobertRendell OP wanted to treat an empty string `\"\"` the same as `undefined`, but for Zod an empty string is still a valid non-missing string, therefore the validation is a little bit more tricky.\n- Thank you, this does trick. However, might want to change the order to `[z.string().min(4), z.string().length(0)]` so that the error message for `min(4)` takes precedence over `length(0)`.\n- Thanks! I was looking for `scheme_type: z.number().or(z.literal(\"\")),` where MUI select required a default empty string, but I wanted the value to remain a number.\n- Put in plain English, I read this as \"Must be a string, with a minimum of four characters, which is optional, and the only other valid option is an empty string, that's ok as well.\n- I'm using Yup with my next project and it works a lot better.\n- Zod just got fully rewritten with v4","metadata":{"transformedAt":"2026-08-18T18:33:48.865Z","totalAnswersIncluded":1,"totalCodeBlocksIncluded":16,"totalLines":195,"estimatedTokens":1408}}8{"id":"stack-76536978","source":"stackoverflow","questionId":76536978,"title":"How to get zod to read input as number and not text","tags":["reactjs","typescript","forms","zod"],"text":"Title: How to get zod to read input as number and not text\nTags: reactjs, typescript, forms, zod\nSource: Stack Overflow\n\nQuestion:\nI am trying to make an input that should take in a number between a certain range. When I submit it, zod says it expected a number but got a string.\n\n```\nimport {z} from \"zod\"\nimport { fromZodError } from \"zod-validation-error\";\n\n//give this file it's own unique name to identify the form it uses\nexport const creditCardData = z.object({\n //------name------\n firstName: z.string().min(3, 'Min Length must be 3').max(10, 'Max Length must be 10'),\n age: z.number().min(1).max(99).int()\n})\n\nexport const defaultCardData={\n firstName:'',\n age: 0\n}\n\nexport type CardData = z.infer\n\n//form submit function\nexport const handleSubmit = (\nevent: React.FormEvent,\nsubmission: CardData,\nisError: (val: boolean) => void,\nisLoading: (val: boolean) => void\n) => {\n event.preventDefault();\n\n isLoading(true)\n const results = creditCardData.safeParse(submission);\n if (!results.success) {\n const errorType = fromZodError(results.error);\n console.log(errorType.message);\n isLoading(false)\n isError(true)\n\n } else {\n isError(false)\n isLoading(false)\n //put api call\n console.log(results.data);\n}\n};\n```\n\nHere is my zod file where I do my validation\n\n```\nimport { useState } from \"react\";\nimport { CardData, defaultCardData, handleSubmit } from \"./validation/zod\";\nimport Input from \"./components/Input\";\n\nfunction App() {\n //state date for form\n const [data, setData] = useState(defaultCardData);\n //loading and function\n const [loading, setLoading] = useState(false);\n const isLoading = (val: boolean) => setLoading(val);\n //error and function\n const [error, setError] = useState(false);\n const isError = (val: boolean) => setError(val);\n\n return (\n \n \n\n### Card Data\n\n handleSubmit(event, data, isError, isLoading)}\n >\n {/* //first name */}\n {\n setData({ ...data, firstName: e.target.value });\n }}\n />\n {/* //age */}\n {\n setData({ ...data, age: e.target.value });\n }}\n />\n {/* //submit */}\n \n Submit\n \n {loading && Loading...\n\n}\n {error && Error on submission\n\n}\n \n \n );\n}\n\nexport default App;\n```\n\nand here is the part where I have the user input. When I submit I get the error \"Validation error: Expected number, received string at \"age\". \"\n\n========================================\n\nTop Answer:\nAs per the Zod documentation, Zod now provides a more convenient way to coerce primitive values.\n\n```\nage: z.coerce.number().gte(18, 'Must be 18 and above');\n```\n\n========================================\n\nCode:\n```text\nimport {z} from \"zod\"\nimport { fromZodError } from \"zod-validation-error\";\n\n//give this file it's own unique name to identify the form it uses\nexport const creditCardData = z.object({\n    //------name------\n    firstName: z.string().min(3, 'Min Length must be 3').max(10, 'Max Length must be 10'),\n    age: z.number().min(1).max(99).int()\n})\n\nexport const defaultCardData={\n    firstName:'',\n    age: 0\n}\n\nexport type CardData = z.infer<typeof creditCardData>\n\n//form submit function\nexport const handleSubmit = (\nevent: React.FormEvent<HTMLFormElement>,\nsubmission: CardData,\nisError: (val: boolean) => void,\nisLoading: (val: boolean) => void\n) => {\n    event.preventDefault();\n\n    isLoading(true)\n    const results = creditCardData.safeParse(submission);\n    if (!results.success) {\n        const errorType = fromZodError(results.error);\n        console.log(errorType.message);\n        isLoading(false)\n        isError(true)\n\n    } else {\n    isError(false)\n    isLoading(false)\n    //put api call\n    console.log(results.data);\n}\n};\n```\n\n```text\nimport { useState } from \"react\";\nimport { CardData, defaultCardData, handleSubmit } from \"./validation/zod\";\nimport Input from \"./components/Input\";\n\nfunction App() {\n  //state date for form\n  const [data, setData] = useState<CardData>(defaultCardData);\n  //loading and function\n  const [loading, setLoading] = useState(false);\n  const isLoading = (val: boolean) => setLoading(val);\n  //error and function\n  const [error, setError] = useState(false);\n  const isError = (val: boolean) => setError(val);\n\n  return (\n    <main className=\"min-h-screen flex justify-center flex-col items-center text-white\">\n      <h1 className=\"text-2xl font-bold \">Card Data</h1>\n\n      <form\n        className=\"text-black\"\n        onSubmit={(event) => handleSubmit(event, data, isError, isLoading)}\n      >\n        {/* //first name */}\n        <Input\n          label=\"First Name \"\n          id=\"firstName\"\n          value={data.firstName}\n          handleChange={(e: { target: { value: string } }) => {\n            setData({ ...data, firstName: e.target.value });\n          }}\n        />\n        {/* //age */}\n        <Input\n          label=\"Age \"\n          id=\"age\"\n          value={data.age}\n          type=\"number\"\n          handleChange={(e: { target: { value: number } }) => {\n            setData({ ...data, age: e.target.value });\n          }}\n        />\n        {/* //submit */}\n        <button\n          className=\"block mt-4 p-2 bg-white border-black border-2 rounded-md\"\n          type=\"submit\"\n        >\n          Submit\n        </button>\n        {loading && <p>Loading...</p>}\n        {error && <p>Error on submission</p>}\n      </form>\n    </main>\n  );\n}\n\nexport default App;\n```\n\n```text\nage : z.preprocess((a) => parseInt(z.string().parse(a),10),\nz.number().gte(18, 'Must be 18 and above'))\n```\n\n```text\nage: z.coerce.number().gte(18, 'Must be 18 and above');\n```\n\n========================================\n\nComments:\n- Yes, but 0 is always less than 18.\n- I wanted to say `z.coerce.number()` will parse empty strings as 0. So if one's condition allows for 0, they can explicitly prevent empty strings using pipe: `z.string().nonempty().pipe(z.coerce.number().min(-90).max(90&zwnj;&#8203;‌​‌​‌​))`","metadata":{"transformedAt":"2026-08-18T18:33:48.865Z","totalAnswersIncluded":1,"totalCodeBlocksIncluded":4,"totalLines":235,"estimatedTokens":1444}}9{"id":"stack-76842580","source":"stackoverflow","questionId":76842580,"title":"How to validate a field in Zod depending on the value of another field?","tags":["javascript","reactjs","typescript","zod"],"text":"Title: How to validate a field in Zod depending on the value of another field?\nTags: javascript, reactjs, typescript, zod\nSource: Stack Overflow\n\nQuestion:\nI have a schema and I need to make it so that the **role** field is only validated when the value of the **subject** field is 1, otherwise the **role** should not be validated at all\n\n```\nconst schema = z.object({\n subject: z.number().default(0),\n gender: z.object({\n owner: z.number(),\n stranger: z.number().array().min(1),\n }),\n age: z.object({\n owner: z.number(),\n stranger: z.number().array().min(1),\n }),\n role: z.object({\n owner: z.number(),\n stranger: z.number(),\n }),\n});\n```\n\nI tried to use the refine method but it was unsuccessful. In all the code examples that I looked at, the refine only processed the field on which this method was called. In my case, I need to process another field\n\n========================================\n\nCode:\n```text\nconst schema = z.object({\n  subject: z.number().default(0),\n  gender: z.object({\n    owner: z.number(),\n    stranger: z.number().array().min(1),\n  }),\n  age: z.object({\n    owner: z.number(),\n    stranger: z.number().array().min(1),\n  }),\n  role: z.object({\n    owner: z.number(),\n    stranger: z.number(),\n  }),\n});\n```\n\n```text\nconst schema = z.object({\n  subject: z.number().default(0),\n  role: z.object({\n    owner: z.number(),\n    stranger: z.number(),\n  }),\n}).refine(data => data.subject !== 1 || (data.subject === 1 && data.role), {\n  message: \"Role field is required when subject equals 1\",\n  path: ['role'] // Pointing out which field is invalid\n});\n```\n\n```text\n.refine(validator: (data:T)=>any, params?: RefineParams)\n```\n\n========================================\n\nComments:\n- Please post your failing code with refine because this is the correct way to do it\n- Just `refine` the entire object?\n- Yes, this is the correct way to do it. The problem was that I was using **.refine** for the role field when I needed to use it for the schema as a whole\n- Thank you! It worked! However, I had to add an **.optional()** to the role field because without it it still validated even if subject = 0","metadata":{"transformedAt":"2026-08-18T18:33:48.865Z","totalAnswersIncluded":0,"totalCodeBlocksIncluded":3,"totalLines":72,"estimatedTokens":529}}10{"id":"stack-70415330","source":"stackoverflow","questionId":70415330,"title":"Do not allow extra properties with zod parse","tags":["javascript","typescript","zod"],"text":"Title: Do not allow extra properties with zod parse\nTags: javascript, typescript, zod\nSource: Stack Overflow\n\nQuestion:\nI'm using `zod` for validation. It seems like if I define a schema and then `parse()` some input with some extra properties that aren't even in the schema, `zod` parses the input as valid but just removes those keys.\n\n```\nimport { z } from 'zod'\n\nconst schema = z.object({\n foo: z.string(),\n bar: z.number() \n})\n\n// this validates fine, printing { foo: 'hello', bar: 1 }\nconsole.log(schema.parse({ foo: 'hello', bar: 1, baz: true }))\n```\n\nHowever, extra input properties is not something I'd like to ignore, instead I'd like to throw a useful error when that happens, reporting the keys of the extra properties.\n\nIs there a way to do that with `zod`?\n\n========================================\n\nTop Answer:\nthis works for my need\n\n```\nimport { ZodType, ZodSafeParseResult } from \"zod/v4\"\n\nexport const strictlyTypedSafeParse = (\n schema: ZodType,\n input: Input,\n): ZodSafeParseResult => schema.safeParse(input)\n\nexport const CodeSchema = z.object({ code: z.string() })\n\nexport type CodeSchemaType = z.infer\n\nconst res1 = strictlyTypedSafeParse(CodeSchema, { code }) // ✅\nconst res2 = strictlyTypedSafeParse(CodeSchema, code) // ❌\n```\n\n========================================\n\nCode:\n```text\nimport { z } from 'zod'\n\nconst schema = z.object({\n  foo: z.string(),\n  bar: z.number()      \n})\n\n// this validates fine, printing { foo: 'hello', bar: 1 }\nconsole.log(schema.parse({ foo: 'hello', bar: 1, baz: true }))\n```\n\n```text\nzod\n```\n\n```text\nparse()\n```\n\n```text\nzod\n```\n\n```text\nzod\n```\n\n```text\nconst schema = z.object({\n  foo: z.string(),\n  bar: z.number()      \n}).strict();\n```\n\n```js\nimport { ZodType, ZodSafeParseResult } from \"zod/v4\"\n\nexport const strictlyTypedSafeParse = <Input, Output = Input>(\n  schema: ZodType<Output, Input>,\n  input: Input,\n): ZodSafeParseResult<Output> => schema.safeParse(input)\n\nexport const CodeSchema = z.object({ code: z.string() })\n\nexport type CodeSchemaType = z.infer<typeof CodeSchema>\n\nconst res1 = strictlyTypedSafeParse<CodeSchemaType>(CodeSchema, { code }) // ✅\nconst res2 = strictlyTypedSafeParse<CodeSchemaType>(CodeSchema, code) // ❌\n```\n\n```text\nstrictObject()\n```\n\n```text\nobject()\n```\n\n========================================\n\nComments:\n- Ah great, thanks! Even throws an error with a code `unrecognized_keys` and an array of those keys.\n- It works, but how to make it as default? I don't want to pass .strict to every z.object.\n- Using `z.strictObject` instead of `z.object` solved my issue.\n- Note, `z.strict()` does not affect for nested objects.","metadata":{"transformedAt":"2026-08-18T18:33:48.865Z","totalAnswersIncluded":1,"totalCodeBlocksIncluded":9,"totalLines":113,"estimatedTokens":655}}11{"id":"stack-72172857","source":"stackoverflow","questionId":72172857,"title":"How omit certain value from nested zod scheme?","tags":["reactjs","react-hook-form","zod"],"text":"Title: How omit certain value from nested zod scheme?\nTags: reactjs, react-hook-form, zod\nSource: Stack Overflow\n\nQuestion:\nI have the following zod schema, and in some cases there is a field I would like to omit from the schema entirely.\nI can't just make it optional. I suspect there is some way do it with zod directly. Is there a way to omit fields or to preprocess the schema in some way?\n\nFor example, how I can use this schema without this nested field.\n\n```\nconst schema = z.object({\n name: z.number(),\n age: z.number(),\n data: z.array(\n z.object({\n id: z.string().optional(),\n name: z.string().nonempty().optional(),\n })\n )\n});\n\nconst test = schema.shape.data //. ??? how can I omit the name field? \ntype typeTest = z.infer; // just data without name field\n```\n\nHow I can omit this nested value?\n\n========================================\n\nTop Answer:\n**Correct answer**\n\n```\nconst schema = z.object({\n name: z.number(),\n age: z.number(),\n data: z.array(\n z.object({\n id: z.string().optional(),\n name: z.string().nonempty().optional()\n })\n )\n});\n\nconst test = schema.shape.data.element.omit({ name: true }).array(); \ntype typeTest = z.infer;\n```\n\n========================================\n\nCode:\n```js\nconst schema = z.object({\n  name: z.number(),\n  age: z.number(),\n  data: z.array(\n    z.object({\n      id: z.string().optional(),\n      name: z.string().nonempty().optional(),\n    })\n  )\n});\n\nconst test = schema.shape.data //. ??? how can I omit the name field? \ntype typeTest = z.infer<typeof test>; // just data without name field\n```\n\n```js\nconst test = schema.shape.data.element.omit({ name: true }).array();\n```\n\n```js\nimport { z } from 'zod';\n\nconst dataSchema = z.object({\n  id: z.string().optional(),\n  someOtherField: z.number(),\n});\n\nconst namedSchema = z.object({\n  name: z.string().nonempty().optional(),\n});\n\nconst fullDataSchema = dataSchema.merge(namedSchema);\n\ntype Data = z.TypeOf<typeof dataSchema>;\ntype FullData = z.TypeOf<typeof fullDataSchema>;\n```\n\n```js\nimport { z } from 'zod';\n\nconst dataSchema = z.object({\n  id: z.string().optional(),\n  someOtherField: z.number(),\n  name: z.string().nonempty().optional(),\n});\n\nconst noNameDataSchema = dataSchema.omit({ name: true });\n\ntype Data = z.TypeOf<typeof noNameDataSchema>;\n```\n\n```text\nmerge\n```\n\n```text\nomit\n```\n\n```text\ntypeof\n```\n\n```text\nconst schema = z.object({\n  name: z.number(),\n  age: z.number(),\n  data: z.array(\n    z.object({\n      id: z.string().optional(),\n      name: z.string().nonempty().optional()\n    })\n  )\n});\n\nconst test = schema.shape.data.element.omit({ name: true }).array(); \ntype typeTest = z.infer<typeof test>;\n```\n\n========================================\n\nComments:\n- Hi there, I've edited my answer to better match with your expectations. You're right that I misunderstood which field you were trying to omit and sort of conflated two options. I omitted the outer `name` field in the first part. I think the later part of my answer was still valid, and I also link to docs and add some more explanations and alternatives so I think there's still value in leaving my answer there. Were you aware of the edit option? In this case it feels a bit more sensible to me than duplicating the answer to fix a small misconception.","metadata":{"transformedAt":"2026-08-18T18:33:48.865Z","totalAnswersIncluded":1,"totalCodeBlocksIncluded":8,"totalLines":136,"estimatedTokens":809}}12{"id":"stack-71185664","source":"stackoverflow","questionId":71185664,"title":"Why does Zod make all my schema fields optional?","tags":["typescript","express","zod"],"text":"Title: Why does Zod make all my schema fields optional?\nTags: typescript, express, zod\nSource: Stack Overflow\n\nQuestion:\nI am using Zod inside my Express & TypeScript & Mongoose API project and when trying to validate my user input against the user schema it returns types conflicts:\n\n```\nArgument of type '{ firstName?: string; lastName?: string; password?: string; passwordConfirmation?: string; email?: string; }' is not assignable to parameter of type 'UserInput'.\n Property 'email' is optional in type '{ firstName?: string; lastName?: string; password?: string; passwordConfirmation?: string; email?: string; }' but required in type 'UserInput'\n```\n\nHere is the schema def:\n\n```\nexport const createUserSchema = object({\n body: object({\n firstName: string({\n required_error: 'First name is required',\n }),\n lastName: string({\n required_error: 'Last name is required',\n }).nonempty(),\n password: string({\n required_error: 'Password is required',\n })\n .nonempty()\n .min(6, 'Password too short - should be 6 chars minimum'),\n\n passwordConfirmation: string({\n required_error: 'Confirm password is required',\n }),\n email: string({\n required_error: 'Email is required',\n })\n .email('Not a valid email')\n .nonempty(),\n }).refine((data) => data.password === data.passwordConfirmation, {\n message: 'Passwords do not match',\n path: ['passwordConfirmation'],\n }),\n});\n\nexport type CreateUserInput = Omit, 'body.passwordConfirmation'>;\n\nexport interface UserInput {\n email: string;\n firstName: string;\n lastName: string;\n password: string;\n}\n```\n\nHow to make these Zod schema fields all not optional as it is making it optional by default?\n\n========================================\n\nTop Answer:\nAs pointed out by @pr0gramist in the comments, the accepted answer should be to add this setting in your `tsconfig.json`:\n\n```\n{\n \"compilerOptions\": {\n \"strictNullChecks\": true \n }\n}\n```\n\nDepending on your default zod configuration, you may need to add this in your schemas as well:\n\n```\nrequiredField: z.string().min(1)\n```\n\nThis method is less intrusive than a `\"strict\": true`, which adds more typescript constraints to your code base.\n\n========================================\n\nCode:\n```text\nArgument of type '{ firstName?: string; lastName?: string; password?: string; passwordConfirmation?: string; email?: string; }' is not assignable to parameter of type 'UserInput'.\n      Property 'email' is optional in type '{ firstName?: string; lastName?: string; password?: string; passwordConfirmation?: string; email?: string; }' but required in type 'UserInput'\n```\n\n```text\nexport const createUserSchema = object({\n  body: object({\n    firstName: string({\n      required_error: 'First name is required',\n    }),\n    lastName: string({\n      required_error: 'Last name is required',\n    }).nonempty(),\n    password: string({\n      required_error: 'Password is required',\n    })\n      .nonempty()\n      .min(6, 'Password too short - should be 6 chars minimum'),\n\n    passwordConfirmation: string({\n      required_error: 'Confirm password is required',\n    }),\n    email: string({\n      required_error: 'Email is required',\n    })\n      .email('Not a valid email')\n      .nonempty(),\n  }).refine((data) => data.password === data.passwordConfirmation, {\n    message: 'Passwords do not match',\n    path: ['passwordConfirmation'],\n  }),\n});\n\nexport type CreateUserInput = Omit<TypeOf<typeof createUserSchema>, 'body.passwordConfirmation'>;\n\n\nexport interface UserInput {\n  email: string;\n  firstName: string;\n  lastName: string;\n  password: string;\n}\n```\n\n```json\n{\n    \"compilerOptions\": {\n        \"strict\": true   \n    }\n}\n```\n\n```text\nstrict: true\n```\n\n```text\nimport { object, string, z } from 'zod';\n\nexport const userSchema = object({\n  firstName: string({\n    required_error: 'First name is required',\n  }),\n  lastName: string({\n    required_error: 'Last name is required',\n  }).nonempty(),\n  password: string({\n    required_error: 'Password is required',\n  })\n    .nonempty()\n    .min(6, 'Password too short - should be 6 chars minimum'),\n  email: string({\n    required_error: 'Email is required',\n  })\n    .email('Not a valid email')\n    .nonempty(),\n});\ntype userSchema = z.infer<typeof userSchema>;\n\nexport const createUserSchema = object({\n  body: userSchema\n    .extend({\n      passwordConfirmation: string({\n        required_error: 'Confirm password is required',\n      }),\n    })\n    .refine((data) => data.password === data.passwordConfirmation, {\n      message: 'Passwords do not match',\n      path: ['passwordConfirmation'],\n    }),\n});\ntype createUserSchema = z.infer<typeof createUserSchema>;\n\nconst us: userSchema = {\n  email: '',\n  firstName: '',\n  lastName: '',\n  password: '',\n};\n\nconst cui: createUserSchema = {\n  body: {\n    email: '',\n    firstName: '',\n    lastName: '',\n    password: '',\n    passwordConfirmation: '',\n  },\n};\n```\n\n```text\n{\n    \"compilerOptions\": {\n        \"strictNullChecks\": true   \n    }\n}\n```\n\n```text\nrequiredField: z.string().min(1)\n```\n\n```text\ntsconfig.json\n```\n\n```text\n\"strict\": true\n```\n\n```text\n.nonempty()\n```\n\n```text\n.min(1)\n```\n\n```text\nz\n    .string({\n      required_error: \"X is required\"\n    })\n```\n\n```text\nmin()\n```\n\n========================================\n\nComments:\n- Can we achieve this without strict mode? I mean... I'm working in quite a huge project that would require a lot of work to change that...\n- @caeus seems like \"strictNullChecks\": true instead of \"strict\": true is enough for non-optional fields. While this probably still force you to migrate some of code I think it will be much easier\n- I had set `\"strict\": true` but then saw later down the config I had set `\"strictNullChecks\": false` which threw me for a loop. Setting both to `true` fixed this issue for me. Hope that helps someone else!\n- @Artokun, for anyone stumbling upon this at a later point. `\"strict\": true` expands into the following options (all set to true): `noImplicitAny noImplicitThis alwaysStrict strictBindCallApply strictNullChecks strictFunctionTypes strictPropertyInitialization`. So in your case, you could've just removed `strictNullChecks` and set just `strict` to true.\n- I am still getting this error even *with* having `strict: true`: github.com/colinhacks/zod/issues/3293\n- Thanks this was exactly what I needed since my project still needed to be `\"strict\": false`\n- `.nonempty()` is deprecated. Come out with something else now.\n- The correct way is `ts z .string({ required_error: \"X is required\" })`\n- The correct way is `ts z .string({ required_error: \"X is required\" })`","metadata":{"transformedAt":"2026-08-18T18:33:48.865Z","totalAnswersIncluded":1,"totalCodeBlocksIncluded":13,"totalLines":242,"estimatedTokens":1633}}13{"id":"stack-77201810","source":"stackoverflow","questionId":77201810,"title":"shadcn Input + Form + Zod \"A component is changing an uncontrolled input to be controlled\"","tags":["reactjs","forms","input","zod","shadcnui"],"text":"Title: shadcn Input + Form + Zod \"A component is changing an uncontrolled input to be controlled\"\nTags: reactjs, forms, input, zod, shadcnui\nSource: Stack Overflow\n\nQuestion:\n**A little background**\n\nI'm using Shadcn UI library and Zod to create some simple forms in my Next.js React app. The inputs are of type `select` and `text`.\n\n**The problem**\n\nI'm following Shadcn documentation on how to set up the form with Zod and Shadcn's ui components but I get an error when the value of the `text` input is changing:\n\nWarning: A component is changing an uncontrolled input to be controlled. This is likely caused by the value changing from undefined to a defined value, which should not happen.\n\n**Worth mentioning**\n\nThe error only occurs when changing the `text` (username) input value.\n\nAlso, the form is working properly despite the error.\n\n**What I've tried**\n\nIve looked up the error and I found answers saying to add a `value` or `defaultValue` after the `{...field}` with a combination of a `useState('')` hook, which solved the error but now it won't let me submit the form.\n\n**Code**\n\n```\n'use client'\nimport {\n Form,\n FormControl,\n FormDescription,\n FormField,\n FormItem,\n FormLabel,\n FormMessage,\n } from \"@/components/ui/form\"\nimport { useForm } from 'react-hook-form'\nimport { zodResolver } from \"@hookform/resolvers/zod\"\nimport * as z from \"zod\"\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"@/components/ui/select\"\nimport { toast } from \"@/components/ui/use-toast\"\nimport Link from \"next/link\"\nimport { Input } from \"@/components/ui/input\"\nimport { ReactNode, useState } from \"react\"\nconst FormSchema = z.object({\n email: z\n .string({\n required_error: \"Please select an email to display.\",\n })\n .email(),\n username: z.string(),\n \n})\n\nconst ZodForm = () => {\n\n const form = useForm>({\n resolver: zodResolver(FormSchema),\n })\n \n function onSubmit(data: z.infer) {\n console.log(data);\n \n toast({\n title: \"You submitted the following values:\",\n description: (\n \n `{JSON.stringify(data, null, 2)}`\n \n ),\n })\n }\n\n return (\n \n \n (\n \n Email\n \n \n \n \n \n \n \n m@example.com\n m@google.com\n m@support.com\n \n \n \n You can manage email addresses in your{\" \"}\n email settings.\n \n \n \n )}\n />\n (\n \n Username\n \n \n \n \n This is your public display name.\n \n \n \n )}\n />\n Submit\n \n \n )\n}\n\nexport default ZodForm\n```\n\n========================================\n\nTop Answer:\nI was facing the problem like you and I resolved the problem by following the few steps:\n\n- Setting the default values first.\n\n```\nconst form = useForm({\n //...\n mode: 'onChange',\n defaultValues: initialValue,\n});\n```\n\n- Load the data from API.\n\n```\nuseEffect(() => {\n if (props.data.id) {\n getData(props.data.id).then((data) => {\n form.reset(data);\n setData(data);\n });\n }\n }, [props.data.id, form]);\n```\n\nHope that help.\n\n========================================\n\nCode:\n```text\n'use client'\nimport {\n    Form,\n    FormControl,\n    FormDescription,\n    FormField,\n    FormItem,\n    FormLabel,\n    FormMessage,\n  } from \"@/components/ui/form\"\nimport { useForm } from 'react-hook-form'\nimport { zodResolver } from \"@hookform/resolvers/zod\"\nimport * as z from \"zod\"\nimport {\n  Select,\n  SelectContent,\n  SelectItem,\n  SelectTrigger,\n  SelectValue,\n} from \"@/components/ui/select\"\nimport { toast } from \"@/components/ui/use-toast\"\nimport Link from \"next/link\"\nimport { Input } from \"@/components/ui/input\"\nimport { ReactNode, useState } from \"react\"\nconst FormSchema = z.object({\n  email: z\n    .string({\n      required_error: \"Please select an email to display.\",\n    })\n    .email(),\n    username: z.string(),\n \n})\n\nconst ZodForm = () => {\n\n  const form = useForm<z.infer<typeof FormSchema>>({\n    resolver: zodResolver(FormSchema),\n  })\n  \n  function onSubmit(data: z.infer<typeof FormSchema>) {\n    console.log(data);\n    \n    toast({\n      title: \"You submitted the following values:\",\n      description: (\n        <pre className=\"mt-2 w-[340px] rounded-md bg-slate-950 p-4\">\n          <code className=\"text-white\">{JSON.stringify(data, null, 2)}</code>\n        </pre>\n      ),\n    })\n  }\n\n\n  return (\n    <Form {...form}>\n      <form onSubmit={form.handleSubmit(onSubmit)} className=\"w-2/3 space-y-6\">\n        <FormField\n          control={form.control}\n          name=\"email\"\n          render={({ field }) => (\n            <FormItem>\n              <FormLabel>Email</FormLabel>\n              <Select onValueChange={field.onChange} defaultValue={field.value}>\n                <FormControl>\n                  <SelectTrigger>\n                    <SelectValue placeholder=\"Select a verified email to display\" />\n                  </SelectTrigger>\n                </FormControl>\n                <SelectContent>\n                  <SelectItem value=\"m@example.com\">m@example.com</SelectItem>\n                  <SelectItem value=\"m@google.com\">m@google.com</SelectItem>\n                  <SelectItem value=\"m@support.com\">m@support.com</SelectItem>\n                </SelectContent>\n              </Select>\n              <FormDescription>\n                You can manage email addresses in your{\" \"}\n                <Link href=\"/examples/forms\">email settings</Link>.\n              </FormDescription>\n              <FormMessage />\n            </FormItem>\n          )}\n        />\n        <FormField\n          control={form.control}\n          name={'username'}\n          render={({ field }) => (\n            <FormItem>\n              <FormLabel>Username</FormLabel>\n              <FormControl>\n                <Input placeholder=\"shadcn\" {...field}  />\n              </FormControl>\n              <FormDescription>\n                This is your public display name.\n              </FormDescription>\n              <FormMessage />\n            </FormItem>\n          )}\n        />\n        <button type=\"submit\">Submit</button>\n      </form>\n    </Form>\n  )\n}\n\nexport default ZodForm\n```\n\n```text\nselect\n```\n\n```text\ntext\n```\n\n```text\ntext\n```\n\n```text\ntext\n```\n\n```text\nvalue\n```\n\n```text\ndefaultValue\n```\n\n```text\n{...field}\n```\n\n```text\nuseState('')\n```\n\n```text\n<FormField\n  control={form.control}\n  name=\"username\"\n  render={({ field }) => (\n    <FormItem>\n      <FormLabel>Username</FormLabel>\n      <FormControl>\n        <Input {...field} />\n      </FormControl>\n      <FormDescription>This is your public display name.</FormDescription>\n      <FormMessage />\n    </FormItem>\n  )}\n/>\n```\n\n```text\nuseForm({\n  defaultValues: {\n    username: \"\"\n  }\n})\n```\n\n```text\ndefaultValues\n```\n\n```text\nuseForm\n```\n\n```text\ndefaultValues\n```\n\n```text\n<FormField />\n```\n\n```text\n<Input {...field} />\n```\n\n```text\nfield\n```\n\n```text\nref\n```\n\n```text\nvalue\n```\n\n```text\nonChange\n```\n\n```text\nonBlur\n```\n\n```text\ndisabled\n```\n\n```text\nname\n```\n\n```text\nvalue\n```\n\n```text\nundefined\n```\n\n```text\nconst form = useForm({\n   //...\n   mode: 'onChange',\n   defaultValues: initialValue,\n});\n```\n\n```text\nuseEffect(() => {\n    if (props.data.id) {\n      getData(props.data.id).then((data) => {\n        form.reset(data);\n        setData(data);\n      });\n    }\n  }, [props.data.id, form]);\n```\n\n========================================\n\nComments:\n- FYI for others: unfortunately RHF doesn't support undefined values and for those of us who use Zod, having optional values is fairly standard, along with other validation, like string length. If you're in that camp you need to perform some heuristics I link to in the Github discussion here.","metadata":{"transformedAt":"2026-08-18T18:33:48.865Z","totalAnswersIncluded":1,"totalCodeBlocksIncluded":27,"totalLines":407,"estimatedTokens":1851}}14{"id":"stack-75373940","source":"stackoverflow","questionId":75373940,"title":"How do I create a zod object with dynamic keys?","tags":["typescript","types","zod"],"text":"Title: How do I create a zod object with dynamic keys?\nTags: typescript, types, zod\nSource: Stack Overflow\n\nQuestion:\nWe can create Zod object that validates an object against the keys that are defined in the schema, but I only want to validate if the key is a string not if the key == something\n\nIn typescript we can achieve this by using\n\n```\nRecord;\n```\n\nBut in zod, I tried this one\n\n```\nconst data = z.object({\n [z.string()]: z.string(),\n});\n```\n\nBut it's not working\n\n========================================\n\nCode:\n```text\nRecord<string, string>;\n```\n\n```text\nconst data = z.object({\n  [z.string()]: z.string(),\n});\n```\n\n```js\nconst data = z.record(z.string(), z.string());\n```\n\n```text\nz.record\n```\n\n========================================\n\nComments:\n- It seems that we can also omit the 2nd. parameter: `const data = z.record(z.string());`\n- To be 100% accurate: You can skip the first argument. But in this case it still ends up being `const data = z.record(z.string());`.\n- And for instance, if my data looks like `z.record(z.string(), z.boolean())` there is a way to validate that I have at least 3 true value?\n- You can enforce that with a `superRefine` tacked on at the end. zod.dev/?id=superrefine\n- As of Zod 4, you can no longer omit the 2nd parameter. zod.dev/v4/changelog?id=zrecord\n- I just discovered z.templateLiterals (zod.dev/api#template-literals) With this, ``` data: z.object({ key: z.array(z.record(z.templateLiteral([\"astring\", z.number()]), z.string().nullable())), }), ``` becomes possible in case only some patterns are allowed","metadata":{"transformedAt":"2026-08-18T18:33:48.865Z","totalAnswersIncluded":0,"totalCodeBlocksIncluded":4,"totalLines":53,"estimatedTokens":390}}15{"id":"stack-76111305","source":"stackoverflow","questionId":76111305,"title":"Zod - Property 'infer' does not exist on type 'typeof import(.../node_modules/zod/lib/external)","tags":["javascript","typescript","zod"],"text":"Title: Zod - Property 'infer' does not exist on type 'typeof import(.../node_modules/zod/lib/external)\nTags: javascript, typescript, zod\nSource: Stack Overflow\n\nQuestion:\nI got the Typescript error:\n\n`Property 'infer' does not exist on type 'typeof import(.../node_modules/zod/lib/external)`\n\non the code:\n`const CampaignForm = z.infer;`\n\nLooking at the docs and node_modules the property is there.\n\n========================================\n\nCode:\n```text\nProperty 'infer' does not exist on type 'typeof import(.../node_modules/zod/lib/external)\n```\n\n```text\nconst CampaignForm = z.infer<typeof CampaignSchema>;\n```\n\n```text\nconst\n```\n\n```text\ntype\n```\n\n```text\ntype CampaignForm = z.infer<typeof CampaignSchema>;\n```\n\n```text\nconst CampaignForm = z.infer<typeof CampaignSchema>;\n```\n\n========================================\n\nComments:\n- Absolutely this was the case.\n- Saved me some frustration there Itay. Thank you.\n- nice. thought I had lost my mind lol","metadata":{"transformedAt":"2026-08-18T18:33:48.866Z","totalAnswersIncluded":0,"totalCodeBlocksIncluded":6,"totalLines":47,"estimatedTokens":240}}16{"id":"stack-75148276","source":"stackoverflow","questionId":75148276,"title":"Email validation with zod","tags":["reactjs","react-hook-form","zod"],"text":"Title: Email validation with zod\nTags: reactjs, react-hook-form, zod\nSource: Stack Overflow\n\nQuestion:\nI have an email input and i want to validate that the user entered a specific email `\"abcd@fg.com\"` and if not to show specific error message `\"This email is not in our database\"`. I am using zod validation to do that, but how can it be done?\n\n```\nconst LoginSchema = z.object({\n email: z\n .string()\n .min(1, { message: \"This field has to be filled.\" })\n .email(\"This is not a valid email.\")\n })\n});\n```\n\n========================================\n\nTop Answer:\n```\nemail: z.string().email(), //only this is enough\n\nemail: z.string().email({message:\"Email is required\"}), // use this to show custom validation message\n```\n\nzod itself provided validation if we use \".email()\" method with \".string()\" validation\n\n========================================\n\nCode:\n```text\nconst LoginSchema = z.object({\n  email: z\n    .string()\n    .min(1, { message: \"This field has to be filled.\" })\n    .email(\"This is not a valid email.\")\n  })\n});\n```\n\n```text\n\"abcd@fg.com\"\n```\n\n```text\n\"This email is not in our database\"\n```\n\n```js\nconst LoginSchema = z.object({\n  email: z\n    .string()\n    .min(1, { message: \"This field has to be filled.\" })\n    .email(\"This is not a valid email.\")\n    .refine((e) => e === \"abcd@fg.com\", \"This email is not in our database\")\n});\n```\n\n```js\nconst login2 = z.object({\n  email: z\n    .string()\n    .min(1, { message: \"This field has to be filled.\" })\n    .email(\"This is not a valid email.\")\n    .refine(async (e) => {\n      const emails = await fetchEmails();\n      return emails.includes(e);\n    }, \"This email is not in our database\")\n});\n```\n\n```js\nconst login2 = z.object({\n  email: z\n    .string()\n    .min(1, { message: \"This field has to be filled.\" })\n    .email(\"This is not a valid email.\")\n    .refine(async (e) => {\n      // Where checkIfEmailIsValid makes a request to the backend\n      // to see if the email is valid.\n      return await checkIfEmailIsValid(e);\n    }, \"This email is not in our database\")\n});\n```\n\n```text\nrefine\n```\n\n```text\nasync\n```\n\n```text\nparseAsync\n```\n\n```text\nemail: z.string().email(),  //only this is enough\n\nemail: z.string().email({message:\"Email is required\"}), // use this to show custom validation message\n```\n\n```text\nimport { $api } from \"@/main\"\n\nimport { toast } from \"sonner\"\nimport * as z from \"zod\"\nimport { ShippingMethod } from \"@/entities/selling/customerAgreementSettings\"\n\n// Regex for prohibited characters in the local part of the email\nconst prohibitedChars = /[()<>[\\]:;@\\\\,/\" ]/\n\nexport const getShipmentSummarySchema = (\n  shippingMethod: ShippingMethod,\n  registeredEmail?: string\n) => {\n  return z.object({\n    // Contact Details\n    contact: z\n      .object({\n        first_name: z.string().min(1, \"Required\"),\n        last_name: z.string().min(1, \"Required\"),\n        email_id: z\n          .string()\n          .email()\n          .min(1, \"Required\")\n          .refine(\n            (email) => {\n              const [localPart] = email.split(\"@\")\n\n              // Check if local part has any prohibited characters or consecutive dots\n              return (\n                !prohibitedChars.test(localPart) &&\n                !localPart.startsWith(\".\") &&\n                !localPart.endsWith(\".\") &&\n                !localPart.includes(\"..\")\n              )\n            },\n            {\n              message: \"Email ID contains prohibited characters\",\n            }\n          )\n          .refine(\n            (email) => {\n              const domainPart = email.split(\"@\")[1]\n\n              // Check if domain part has consecutive dots or starts/ends with a dot\n              return (\n                domainPart &&\n                !domainPart.startsWith(\".\") &&\n                !domainPart.endsWith(\".\") &&\n                !domainPart.includes(\"..\")\n              )\n            },\n            {\n              message: \"Email domain contains prohibited characters\",\n            }\n          ),\n        territory: z.string().min(1, \"Required\"),\n        mobile_no: z.string().min(1, \"Required\"),\n      })\n      .refine(\n        async (data) => {\n          if (registeredEmail === data.email_id) {\n            return true\n          }\n\n          const result = await $api.user.is_registered(data.email_id)\n\n          if (result) {\n            toast.error(\n              `User is already registered with this email: ${data.email_id}`\n            )\n            return false\n          }\n          return true\n        },\n        { message: \"Already exists. Use an other email\" }\n      ),\n\n    // Address\n    address: z.object({\n      address_line1: z\n        .string()\n        .min(1, \"Address is required\")\n        .max(shippingMethod?.address_length || 75),\n      address_line2: z\n        .string()\n        .min(1, \"Required\")\n        .max(shippingMethod?.house_number_length || 20),\n      city: z.string().min(1, \"City is required\"),\n      country: z.string().min(1, \"Country is required\"),\n      pincode: z.string().min(1, \"Required\").max(20),\n    }),\n  })\n}\n```\n\n========================================\n\nComments:\n- Specific or from the database?\n- @Konrad now as a specific then later from a return from api\n- Instead of fetching the emails you could send a request which would validate like `return await isValidEmail(e)`\n- That's a great point! If you do that, then there's nothing wrong with the approach. I think I'll edit my answer to include that\n- This should be the correct answer. Those answers suggesting to check in the database and show a different error if it exists are introducing an enumeration attack vector in your application, and if your application is big enough you'll have a bot spamming your endpoint in no time.\n- Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.","metadata":{"transformedAt":"2026-08-18T18:33:48.866Z","totalAnswersIncluded":1,"totalCodeBlocksIncluded":11,"totalLines":209,"estimatedTokens":1500}}17{"id":"stack-74921458","source":"stackoverflow","questionId":74921458,"title":"Does zod have something equivalent to yup's oneOf()","tags":["typescript","validation","yup","zod"],"text":"Title: Does zod have something equivalent to yup's oneOf()\nTags: typescript, validation, yup, zod\nSource: Stack Overflow\n\nQuestion:\nIf I had a property that should be limited to only a few possible values, using Yup I could do something like:\n\n```\nprop: Yup.string().oneOf([5, 10, 15])\n```\n\nI can not seem to find something similar in Zod. Of course, I can do that validation in the following way:\n\n```\nconst allowedValues = [5, 10, 15];\n\nconst schema = z.object({\n prop: z.number().superRefine((val, ctx) => {\n if (allowedValues.includes(val)) return true;\n\n ctx.addIssue({\n message: `${ctx.path} must be one of ${allowedValues}`,\n code: \"custom\",\n });\n return false;\n }),\n});\n```\n\nBut I was wondering if it could be done by writing less code.\n\n========================================\n\nTop Answer:\nIf the type you're dealing with is set of string literals, there's a shorthand operator you can use in newer versions of Zod:\n\n```\ntype Levels = \"One\" | \"Two\" | \"Three\"\n\nconst LevelsSchema = z.enum([\"One\", \"Two\", \"Three\"])\n```\n\n========================================\n\nCode:\n```text\nprop: Yup.string().oneOf([5, 10, 15])\n```\n\n```text\nconst allowedValues = [5, 10, 15];\n\nconst schema = z.object({\n  prop: z.number().superRefine((val, ctx) => {\n    if (allowedValues.includes(val)) return true;\n\n    ctx.addIssue({\n      message: `${ctx.path} must be one of ${allowedValues}`,\n      code: \"custom\",\n    });\n    return false;\n  }),\n});\n```\n\n```js\nconst schema = z.object({\n  prop: z.union([z.literal(5), z.literal(10), z.literal(15)]),\n});\n```\n\n```js\n// This signature might be a bit overkill but these are the types\n// z.literal allows.\nfunction oneOf<T extends string | number | boolean | bigint | null | undefined>(\n  t: readonly [T, T, ...T[]],\n) {\n  // A union must have at least 2 elements so to work with the types it\n  // must be instantiated in this way.\n  return z.union([\n    z.literal(t[0]),\n    z.literal(t[1]),\n    // No pointfree here because `z.literal` takes an optional second parameter\n    ...t.slice(2).map(v => z.literal(v)),\n  ])\n}\n\n// This will be equivalent to the first schema\nconst schema2 = z.object({\n  // This will still typecheck without as const but with weaker\n  // types than the first example.\n  prop: oneOf([5,10,15] as const),\n});\n```\n\n```text\nz.union\n```\n\n```text\nz.literal\n```\n\n```text\n5 | 10 | 15\n```\n\n```text\nnumber\n```\n\n```text\ntype Levels = \"One\" | \"Two\" | \"Three\"\n\nconst LevelsSchema = z.enum([\"One\", \"Two\", \"Three\"])\n```","metadata":{"transformedAt":"2026-08-18T18:33:48.866Z","totalAnswersIncluded":1,"totalCodeBlocksIncluded":9,"totalLines":116,"estimatedTokens":616}}18{"id":"stack-75531294","source":"stackoverflow","questionId":75531294,"title":"Zod - Checking the number of digits on a number type","tags":["javascript","typescript","zod"],"text":"Title: Zod - Checking the number of digits on a number type\nTags: javascript, typescript, zod\nSource: Stack Overflow\n\nQuestion:\nI'm unable to figure out how to check for the number of digits in a number using Zod.\n\nSince I'm converting my string value to a number, I'm unable to use min() or max() to check for the number of digits.\n\nI've tried using lte() and gte() the following when building my schema:\n\n```\nexport const MySchema = z.object({\n type1: z.coerce.string(),\n type2: z.coerce.string(),\n type4: z.coerce.number().lte(5).gte(5),\n type5: z.coerce.number()\n})\n```\n\nMy goal is to limit `type4` to a fix length of 5 digits for validation. What could be an alternative solution? Maybe checking the string length before converting to a number?\n\n========================================\n\nTop Answer:\nI used `.refine` to create a custom validation logic (here is an example for validate postal code).\n\n```\npostalCode: z.coerce\n .number({\n required_error: 'Postal Code is required',\n invalid_type_error: 'Postal Code must be a number',\n })\n .refine((val) => `${val}`.length === 5, 'Postal Code must be 5 digit long')\n```\n\n========================================\n\nCode:\n```text\nexport const MySchema = z.object({\n  type1: z.coerce.string(),\n  type2: z.coerce.string(),\n  type4: z.coerce.number().lte(5).gte(5),\n  type5: z.coerce.number()\n})\n```\n\n```text\ntype4\n```\n\n```js\n// Omitting the wrapper stuff\nz.coerce.number() // Force it to be a number\n  .int() // Make sure it's an integer\n  .gte(10000) // Greater than or equal to the smallest 5 digit int\n  .lte(99999) // Less than or equal to the largest 5 digit int\n```\n\n```text\nconst MySchema = z.object({\n  type1: z.string(),\n  type2: z.string(),\n  type4: z.string().transform((val) => {\n    if (val.length !== 5) throw new Error('Type4 must have 5 digits')\n    return parseInt(val, 10)\n  }),\n  type5: z.number()\n})\n```\n\n```text\npostalCode: z.coerce\n  .number({\n    required_error: 'Postal Code is required',\n    invalid_type_error: 'Postal Code must be a number',\n  })\n  .refine((val) => `${val}`.length === 5, 'Postal Code must be 5 digit long')\n```\n\n```text\n.refine\n```\n\n========================================\n\nComments:\n- Rather than throwing an error directly from the transform function, it's typically a bit better to use the second `ctx` argument to `transform` to `addIssue` so that if you parse this with `safeParse` the error is not thrown.\n- Another thing you could do is use `z.string().length(5)` along with `safeParse` in the transform function to reuse all of the nice error messages `zod` packs with it. For example if we stored the `safeParse` result as `result` then you could `ctx.addIssue(result.error.issues)` when `result.success` is `false`\n- This answer worked perfectly for me since I am working with integers only. However, Zolt&#225;n's solution would also work if I was using decimal values.\n- What happens if there is an exception in the Number() coercer though?","metadata":{"transformedAt":"2026-08-18T18:33:48.866Z","totalAnswersIncluded":1,"totalCodeBlocksIncluded":6,"totalLines":92,"estimatedTokens":737}}19{"id":"stack-75572170","source":"stackoverflow","questionId":75572170,"title":"ZOD validation based on another field","tags":["typescript","zod"],"text":"Title: ZOD validation based on another field\nTags: typescript, zod\nSource: Stack Overflow\n\nQuestion:\nImagine I have an object like\n\n```\n{\n field1: 'test',\n field2: 'test1'\n}\n```\n\nHow I can create the following validation:\n\nIf `field1` and `field2` both are empty - it is not valid\n\nIf `field1` and `field2` both are not empty - it is not valid\n\nOther cases are valid.\n\n========================================\n\nCode:\n```js\n{\n  field1: 'test',\n  field2: 'test1'\n}\n```\n\n```text\nfield1\n```\n\n```text\nfield2\n```\n\n```text\nfield1\n```\n\n```text\nfield2\n```\n\n```text\nconst res = z.object({\n    field1: z.string().optional(),\n    field2: z.string().optional(),\n}) \n    .refine(schema => {\n        return !(\n            schema.field1 === undefined && \n            schema.field2 === undefined ||\n            schema.field2 !== undefined && \n            schema.field1 !== undefined\n        ); \n    }, \"Your message\");\n```\n\n```text\n.refine()\n```\n\n========================================\n\nComments:\n- `type T = {field1: string, field2?: never} | {field1?: never, field2: string};` XORs two types together, I havent used ZOD though so I dont know if thats what you need.\n- FYI, you don't need to use a ternary, just use your expression and it will result in true or false. eg: `refine(schema => schema.field1 === undefined)`","metadata":{"transformedAt":"2026-08-18T18:33:48.866Z","totalAnswersIncluded":0,"totalCodeBlocksIncluded":7,"totalLines":72,"estimatedTokens":327}}20{"id":"stack-77427502","source":"stackoverflow","questionId":77427502,"title":"How to merge multiple Zod (object) schema","tags":["typescript","zod"],"text":"Title: How to merge multiple Zod (object) schema\nTags: typescript, zod\nSource: Stack Overflow\n\nQuestion:\nI've 3 schema for a blog post.\n\n- Image post\n\n- Video post\n\n- Text post\n\nSchema look like this\n\n```\n// will be used for form validation\n\n// text can be added but image required\nconst imagePostSchema = z.object({\n body: z.string().max(500).optional().or(z.literal('')),\n attachmentType: z.literal('img'),\n attachment: // z... image validation is here\n});\n\n// text can be added but video required\nconst videoPostSchema = z.object({\n body: z.string().max(500).optional().or(z.literal('')),\n attachmentType: z.literal('video'),\n attachment: // z... video validation is here\n});\n\n// text is required & other fields must be null\nconst textPostSchema = z.object({\n body: z.string().max(500),\n attachmentType: z.null(),\n attachment: z.null()\n});\n```\n\nNow how to merge this schema's to make one schema so user can make any type of (this 3) post?\n\n========================================\n\nTop Answer:\nyou can create a new Schema by combining all of them in to a single One by spreading those schemas in to the new one\n\n\r\n\r\n\n```\nexport const formSchema = z.object({\n...imagePostSchema.shape,\n...videoPostSchema.shape,\n...textPostSchema.shape,\n});\n```\n\n========================================\n\nCode:\n```js\n// will be used for form validation\n\n// text can be added but image required\nconst imagePostSchema = z.object({\n  body: z.string().max(500).optional().or(z.literal('')),\n  attachmentType: z.literal('img'),\n  attachment: // z... image validation is here\n});\n\n// text can be added but video required\nconst videoPostSchema = z.object({\n  body: z.string().max(500).optional().or(z.literal('')),\n  attachmentType: z.literal('video'),\n  attachment: // z... video validation is here\n});\n\n// text is required & other fields must be null\nconst textPostSchema = z.object({\n  body: z.string().max(500),\n  attachmentType: z.null(),\n  attachment: z.null()\n});\n```\n\n```text\nconst postSchema = z.discriminatedUnion(\"attachmentType\", [\n  imagePostSchema,\n  videoPostSchema,\n  textPostSchema,\n]);\n```\n\n```text\n….or(…)\n```\n\n```text\nz.union(…)\n```\n\n```text\nattachmentType\n```\n\n```text\nconst postSchema = z.union([imagePostSchema, videoPostSchema, textPostSchema]);\n```\n\n```text\nz.union\n```\n\n```text\npostSchema\n```\n\n```text\nconst postSchema = z.intersection(imagePostSchema,videoPostSchema,textPostSchema);\n```\n\n```js\nexport const formSchema = z.object({\n...imagePostSchema.shape,\n...videoPostSchema.shape,\n...textPostSchema.shape,\n});\n```\n\n========================================\n\nComments:\n- That's unionizing, not merging!\n- Thank you very much, you'r solution seems best option, I'm using this schemas with react-hook-form, In there in the `defaultValues`, I was getting excellent auto-completion before, but now I think that reduced but it still works. Is there I'm doing anything wrong or is there any way to improve zod schemas i've?\n- @Md.A.Apu You may want to ask a separate question about that, showing how use use react-hook-form and where you expected an autocompletion that you are not (no longer?) getting\n- However, the question is like `imagePostSchema | videoPostSchema | textPostSchema` in TS, but *intersection* means `imagePostSchema & videoPostSchema & textPostSchema`\n- The maximum amount of parameters is two, not three (like you exemplified).","metadata":{"transformedAt":"2026-08-18T18:33:48.866Z","totalAnswersIncluded":1,"totalCodeBlocksIncluded":10,"totalLines":138,"estimatedTokens":837}}21{"id":"stack-76293159","source":"stackoverflow","questionId":76293159,"title":"How to iterate over properties and get the types in Zod?","tags":["typescript","zod"],"text":"Title: How to iterate over properties and get the types in Zod?\nTags: typescript, zod\nSource: Stack Overflow\n\nQuestion:\nSay you have a basic system like this in Zod:\n\n```\nimport { z } from 'zod'\n\nconst Post = z.object({\n title: z.string(),\n})\n\nconst User = z.object({\n name: z.string(),\n email: z.string().optional(),\n posts: z.array(Post),\n loginCount: z.number().min(1)\n})\n```\n\nHow do you iterate through the properties and inspect the options on the properties?\n\nI see there is a `.shape` property, but how do you do this:\n\n```\nfor (const name in shape) {\n const prop = shape[name]\n\n if (prop.min != null) {\n console.log(`Has min ${prop.min}`)\n }\n if (prop.max != null) {\n console.log(`Has max ${prop.max}`);\n }\n if (prop.optional === true) {\n console.log(`Is optional`);\n }\n if (prop.type) {\n if (prop.type is array) {\n prop.type.forEach(item => {\n console.log(`Has array item type ${item.name}`)\n })\n } else if (prop.type is union) {\n // ... show union type names\n } else {\n // show basic type name\n }\n }\n}\n```\n\nI need to use this definition to, for example:\n\n- Get the keys of each schema\n\n- Get the allowed property type(s) for a property on a schema (so I can know what db table to insert into, for example)\n\n- Make documentation\n\n- Stuff like that.\n\nI don't see any docs for stuff like this and don't want to end up reinventing the wheel by making my own library to do types and type inspection.\n\n========================================\n\nTop Answer:\nComplementary to @Svish's Answer, When using some transpilers like Babel, some `instanceof` expressions break. (Especially when inherting built-in classes like `Error` and `Date`. Read here, and here, and here)\n\nThankfully, Zod keeps the class name of the schema at `schema._def.typeName`.\nSo we can use it like this:\n\n```\nif (schema instanceof ZodObject || schema._def.typeName === \"ZodObject\") {\n\n}\n```\n\n========================================\n\nCode:\n```text\nimport { z } from 'zod'\n\nconst Post = z.object({\n  title: z.string(),\n})\n\nconst User = z.object({\n  name: z.string(),\n  email: z.string().optional(),\n  posts: z.array(Post),\n  loginCount: z.number().min(1)\n})\n```\n\n```text\nfor (const name in shape) {\n  const prop = shape[name]\n\n  if (prop.min != null) {\n    console.log(`Has min ${prop.min}`)\n  }\n  if (prop.max != null) {\n    console.log(`Has max ${prop.max}`);\n  }\n  if (prop.optional === true) {\n    console.log(`Is optional`);\n  }\n  if (prop.type) {\n    if (prop.type is array) {\n      prop.type.forEach(item => {\n        console.log(`Has array item type ${item.name}`)\n      })\n    } else if (prop.type is union) {\n      // ... show union type names\n    } else {\n      // show basic type name\n    }\n  }\n}\n```\n\n```text\n.shape\n```\n\n```text\nif (s instanceof ZodNumber)\n  console.log(s.minValue, s.maxValue)\n```\n\n```text\nif (s instanceof ZodObject)\n  for (const field of schema.shape)\n    // look at each field\n```\n\n```text\nlet required = true;\n\nwhile (s instanceof ZodOptional || s instanceof ZodNullable) {\n  required = false;\n  s = s.unwrap();\n}\n```\n\n```text\nminValue\n```\n\n```text\nmaxValue\n```\n\n```text\nshape\n```\n\n```text\nZodObject\n```\n\n```text\nZodOptional\n```\n\n```text\nZodNullable\n```\n\n```text\nunwrap()\n```\n\n```text\nZodEffects\n```\n\n```text\ninnerType()\n```\n\n```none\nif (schema instanceof ZodObject || schema._def.typeName === \"ZodObject\") {\n\n}\n```\n\n```text\ninstanceof\n```\n\n```text\nError\n```\n\n```text\nDate\n```\n\n```text\nschema._def.typeName\n```\n\n========================================\n\nComments:\n- In case anyone just wants to see their schema in the browser's dev console, I just entered (for my schema creatively named \"FormSchema\") `FormSchema.shape` and it showed me what I wanted to see.\n- I'm getting an error about a missing iterator when I do `for (const field of schema.shape)` for the schema I'm using. But `in` works fine, but only gives the names of the fields.","metadata":{"transformedAt":"2026-08-18T18:33:48.866Z","totalAnswersIncluded":1,"totalCodeBlocksIncluded":20,"totalLines":211,"estimatedTokens":963}}22{"id":"stack-75187583","source":"stackoverflow","questionId":75187583,"title":"Can I validate an exact value with zod?","tags":["zod"],"text":"Title: Can I validate an exact value with zod?\nTags: zod\nSource: Stack Overflow\n\nQuestion:\nValidating a string can be done with a regex. That's easy.\n\n```\nconst myString = z.string().regex(/A string/);\n```\n\nBut what about other data types?\n\nI guess the following could work for number, but it doesn't seem idiomatic.\n\n```\nconst myNumber = z.number().gte(7).lte(7);\n```\n\nIs there a better way?\n\n========================================\n\nCode:\n```js\nconst myString = z.string().regex(/A string/);\n```\n\n```js\nconst myNumber = z.number().gte(7).lte(7);\n```\n\n```js\nconst myNumber = z.literal(7);\n```\n\n```text\nnumber\n```","metadata":{"transformedAt":"2026-08-18T18:33:48.866Z","totalAnswersIncluded":0,"totalCodeBlocksIncluded":4,"totalLines":39,"estimatedTokens":154}}23{"id":"stack-73557949","source":"stackoverflow","questionId":73557949,"title":"Zod error handling with custom error messages on enums","tags":["typescript","enums","zod"],"text":"Title: Zod error handling with custom error messages on enums\nTags: typescript, enums, zod\nSource: Stack Overflow\n\nQuestion:\nI want to validate a gender field with Zod using `z.nativeEnum()`, But my custom error messages don't apply:\n\n```\ngender: z.nativeEnum(Gender, {\n invalid_type_error: 'Le sexe doit être homme ou femme.',\n required_error: 'Le sexe est obligatoire',\n }),\n```\n\nbut when not selecting an option the displayed error is:\n\nhttps://i.sstatic.net/YODIs.png\n\nWhat's the error here ?\n\n========================================\n\nTop Answer:\nIf you want a generic message for all errors, you can set the `message` prop instead of specifying the `errorMap`\n\n```\nz.nativeEnum(Gender, {message: 'custom message for all errors'});\n```\n\n========================================\n\nCode:\n```js\ngender: z.nativeEnum(Gender, {\n        invalid_type_error: 'Le sexe doit être homme ou femme.',\n        required_error: 'Le sexe est obligatoire',\n      }),\n```\n\n```text\nz.nativeEnum()\n```\n\n```js\ngender: z.nativeEnum(Gender, {\n        errorMap: (issue, _ctx) => {\n          switch (issue.code) {\n            case 'invalid_type':\n              return { message: 'Le sexe doit être homme ou femme.' };\n            case 'invalid_enum_value':\n              return { message: 'Le sexe doit être homme ou femme.' };\n            default:\n              return { message: 'Sexe est invalide' };\n          }\n        },\n      }),\n```\n\n```text\nerrorMap\n```\n\n```text\nz.nativeEnum(Gender, {message: 'custom message for all errors'});\n```\n\n```text\nmessage\n```\n\n```text\nerrorMap\n```\n\n========================================\n\nComments:\n- This is 2023 here, somebody would crucify for making this validation lol (just kidding)","metadata":{"transformedAt":"2026-08-18T18:33:48.866Z","totalAnswersIncluded":1,"totalCodeBlocksIncluded":7,"totalLines":78,"estimatedTokens":427}}24{"id":"stack-75285218","source":"stackoverflow","questionId":75285218,"title":"Is there a way to use Zod to validate that a number has up to 2 decimal digits?","tags":["javascript","typescript","zod"],"text":"Title: Is there a way to use Zod to validate that a number has up to 2 decimal digits?\nTags: javascript, typescript, zod\nSource: Stack Overflow\n\nQuestion:\nI have an object with a numeric property. I'd like to make sure that the number has only up to 2 decimal digit.\n\ne.g:\n`1 // good 1.1 // good 1.11 // good 1.111 //bad`\n\nIs there way to do that?\n\nLooked at Zod's documentation and searched the web. Found that i could have done it easily if my property was a string. Not sure about number.\n\n========================================\n\nCode:\n```text\n1 // good 1.1 // good 1.11 // good 1.111 //bad\n```\n\n```text\nz.number().multipleOf(0.01)\n```\n\n```text\nz.number().multipleOf(0.01).parse(0.1 + 0.1 + 0.1)\n```\n\n```text\nz.number()\n  .refine(x => x * 100 - Math.trunc(x * 100)< Number.EPSILON)\n  .parse(0.1 + 0.1  + 0.1) // ok\n```\n\n```text\nrefine()\n```\n\n```text\nNumber.EPSILON\n```\n\n```text\nz.custom()\n```\n\n========================================\n\nComments:\n- THen just convert your nubmer to string `${number}` or number.toString()\n- Tnx for answering @captain-yossarianfromUkraine. At my case i cannot convert the value as the validating is done in a generic layer, i need to define my requirement as a part of the object's schema. WDYT?\n- Using z.custom?\n- tnx @vera. do you think custom / refine are the right way to go here? was afraid that its a hack (?)\n- I don't see how else you're going to do it :p\n- tnx! if there's no other way / a \"best practice\" for that - this solution is fine by me.\n- Try to use `Number.EPSILON` to handle `0.1+0.2` issue. See example which is taken from docs\n- @captain-yossarianfromUkraine you're right. I tried yesterday with EPSILON and comparison did return `false` to me. But today it's `true` &#175;\\_(ツ)_/&#175;\n- Tnx for this answer! Great! I'm actually fine with '0.1 + 0.1 + 0.1' to fail, i'm getting an object with a number property. This number has to be with only up to two decimal digits, I don't care how it was created, if my api's user got `0.300000000004` because he/she added '0.1 + 0.1 + 0.1' and did not validate at his side that there are more decimal digits its his own problem. tnx again!","metadata":{"transformedAt":"2026-08-18T18:33:48.866Z","totalAnswersIncluded":0,"totalCodeBlocksIncluded":7,"totalLines":59,"estimatedTokens":535}}25{"id":"stack-74721814","source":"stackoverflow","questionId":74721814,"title":"Conditional keys based on value of another key with Zod","tags":["typescript","rest","types","zod","trpc.io"],"text":"Title: Conditional keys based on value of another key with Zod\nTags: typescript, rest, types, zod, trpc.io\nSource: Stack Overflow\n\nQuestion:\nI'm making a project with the TMDB API and trying to make it super type-safe to reinforce some of the TypeScript stuff I'm learning. I'm using Zod to describe the shape of the data returned by the API.\n\nHowever, I've noticed that depending on the request parameters, the API can send back data with different keys. Specifically, if the API is sending back data from the \"trending\" endpoint where `data.media_type = \"movie\"` it also has the keys `title`, `original_title`, and `release_date`. But if `data.media_type = \"tv\"`, those three keys are renamed `name`, `original_name`, and `first_air_date`, respectively, as well as a new key of `origin_country` being added.\n\nAs a result, I described the shape of my data like this:\n\n```\nconst mediaType = [\"all\", \"movie\", \"tv\", \"person\"] as const\n\nconst dataShape = z.object({\n page: z.number(),\n results: z.array(z.object({\n adult: z.boolean(),\n backdrop_path: z.string(),\n first_air_date: z.string().optional(),\n release_date: z.string().optional(),\n genre_ids: z.array(z.number()),\n id: z.number(),\n media_type: z.enum(mediaType),\n name: z.string().optional(),\n title: z.string().optional(),\n origin_country: z.array(z.string()).optional(),\n original_language: z.string().default(\"en\"),\n original_name: z.string().optional(),\n original_title: z.string().optional(),\n overview: z.string(),\n popularity: z.number(),\n poster_path: z.string(),\n vote_average: z.number(),\n vote_count: z.number()\n })),\n total_pages: z.number(),\n total_results: z.number()\n})\n```\n\nBasically, I've added `.optional()` to every troublesome key. Obviously, this isn't very type-safe. Is there a way to specify that the `origin_country` key only exists when `media_type` is equal to `tv`, or that the key `name` or `title` are both a `z.string()`, but whose existence is conditional?\n\nIt may be worth stating that the `media_type` is also specified outside of the returned data, specifically in the input to the API call (which for completeness looks like this, using tRPC):\n\n```\nimport { tmdbRoute } from \"../utils\"\nimport { publicProcedure } from \"../trpc\"\n\nexport const getTrending = publicProcedure\n .input(z.object({\n mediaType: z.enum(mediaType).default(\"all\"),\n timeWindow: z.enum([\"day\", \"week\"]).default(\"day\")\n }))\n .output(dataShape)\n .query(async ({ input }) => {\n return await fetch(tmdbRoute(`/trending/${input.mediaType}/${input.timeWindow}`))\n .then(res => res.json())\n })\n```\n\nAny help is appreciated!\n\nEdit: I have learned about the Zod method of `discriminatedUnion()` since posting this, but if that's the correct approach I'm struggling to implement it. Currently have something like this:\n\n```\nconst indiscriminateDataShape = z.object({\n page: z.number(),\n results: z.array(\n z.object({\n adult: z.boolean(),\n backdrop_path: z.string(),\n genre_ids: z.array(z.number()),\n id: z.number(),\n media_type: z.enum(mediaType),\n original_language: z.string().default(\"en\"),\n overview: z.string(),\n popularity: z.number(),\n poster_path: z.string(),\n vote_average: z.number(),\n vote_count: z.number()\n })\n ),\n total_pages: z.number(),\n total_results: z.number()\n})\n\nconst dataShape = z.discriminatedUnion('media_type', [\n z.object({\n media_type: z.literal(\"tv\"),\n name: z.string(),\n first_air_date: z.string(),\n original_name: z.string(),\n origin_country: z.array(z.string())\n }).merge(indiscriminateDataShape),\n z.object({\n media_type: z.literal(\"movie\"),\n title: z.string(),\n release_date: z.string(),\n original_title: z.string()\n }).merge(indiscriminateDataShape),\n z.object({\n media_type: z.literal(\"all\")\n }).merge(indiscriminateDataShape),\n z.object({\n media_type: z.literal(\"person\")\n }).merge(indiscriminateDataShape)\n])\n```\n\nMaking the request with any value for `media_type` with the above code logs the error `\"Invalid discriminator value. Expected 'tv' | 'movie' | 'all' | 'person'\"`\n\n========================================\n\nCode:\n```js\nconst mediaType = [\"all\", \"movie\", \"tv\", \"person\"] as const\n\nconst dataShape = z.object({\n    page: z.number(),\n    results: z.array(z.object({\n        adult: z.boolean(),\n        backdrop_path: z.string(),\n        first_air_date: z.string().optional(),\n        release_date: z.string().optional(),\n        genre_ids: z.array(z.number()),\n        id: z.number(),\n        media_type: z.enum(mediaType),\n        name: z.string().optional(),\n        title: z.string().optional(),\n        origin_country: z.array(z.string()).optional(),\n        original_language: z.string().default(\"en\"),\n        original_name: z.string().optional(),\n        original_title: z.string().optional(),\n        overview: z.string(),\n        popularity: z.number(),\n        poster_path: z.string(),\n        vote_average: z.number(),\n        vote_count: z.number()\n    })),\n    total_pages: z.number(),\n    total_results: z.number()\n})\n```\n\n```js\nimport { tmdbRoute } from \"../utils\"\nimport { publicProcedure } from \"../trpc\"\n\nexport const getTrending = publicProcedure\n    .input(z.object({\n        mediaType: z.enum(mediaType).default(\"all\"),\n        timeWindow: z.enum([\"day\", \"week\"]).default(\"day\")\n    }))\n    .output(dataShape)\n    .query(async ({ input }) => {\n        return await fetch(tmdbRoute(`/trending/${input.mediaType}/${input.timeWindow}`))\n            .then(res => res.json())\n    })\n```\n\n```js\nconst indiscriminateDataShape = z.object({\n    page: z.number(),\n    results: z.array(\n        z.object({\n            adult: z.boolean(),\n            backdrop_path: z.string(),\n            genre_ids: z.array(z.number()),\n            id: z.number(),\n            media_type: z.enum(mediaType),\n            original_language: z.string().default(\"en\"),\n            overview: z.string(),\n            popularity: z.number(),\n            poster_path: z.string(),\n            vote_average: z.number(),\n            vote_count: z.number()\n        })\n    ),\n    total_pages: z.number(),\n    total_results: z.number()\n})\n\nconst dataShape = z.discriminatedUnion('media_type', [\n    z.object({\n        media_type: z.literal(\"tv\"),\n        name: z.string(),\n        first_air_date: z.string(),\n        original_name: z.string(),\n        origin_country: z.array(z.string())\n    }).merge(indiscriminateDataShape),\n    z.object({\n        media_type: z.literal(\"movie\"),\n        title: z.string(),\n        release_date: z.string(),\n        original_title: z.string()\n    }).merge(indiscriminateDataShape),\n    z.object({\n        media_type: z.literal(\"all\")\n    }).merge(indiscriminateDataShape),\n    z.object({\n        media_type: z.literal(\"person\")\n    }).merge(indiscriminateDataShape)\n])\n```\n\n```text\ndata.media_type = \"movie\"\n```\n\n```text\ntitle\n```\n\n```text\noriginal_title\n```\n\n```text\nrelease_date\n```\n\n```text\ndata.media_type = \"tv\"\n```\n\n```text\nname\n```\n\n```text\noriginal_name\n```\n\n```text\nfirst_air_date\n```\n\n```text\norigin_country\n```\n\n```text\n.optional()\n```\n\n```text\norigin_country\n```\n\n```text\nmedia_type\n```\n\n```text\ntv\n```\n\n```text\nname\n```\n\n```text\ntitle\n```\n\n```text\nz.string()\n```\n\n```text\nmedia_type\n```\n\n```text\ndiscriminatedUnion()\n```\n\n```text\nmedia_type\n```\n\n```text\n\"Invalid discriminator value. Expected 'tv' | 'movie' | 'all' | 'person'\"\n```\n\n```text\nconst schema = {\n  page: 1,\n  results: [],\n  total_pages: 100,\n  total_results: 200,\n}\n```\n\n```text\nconst baseShape = z.object({\n  adult: z.boolean(),\n  backdrop_path: z.string(),\n  genre_ids: z.array(z.number()),\n  id: z.number(),\n  original_language: z.string().default('en'),\n  overview: z.string(),\n  popularity: z.number(),\n  poster_path: z.string(),\n  vote_average: z.number(),\n  vote_count: z.number(),\n});\n\nconst resultShape = z\n  .discriminatedUnion('media_type', [\n    // tv shape\n    z.object({\n      media_type: z.literal('tv'),\n      name: z.string(),\n      first_air_date: z.string(),\n      original_name: z.string(),\n      origin_country: z.array(z.string()),\n    }),\n\n    // movie shape\n    z.object({\n      media_type: z.literal('movie'),\n      title: z.string(),\n      release_date: z.string(),\n      original_title: z.string(),\n    }),\n\n    // all shape\n    z.object({\n      media_type: z.literal('all'),\n    }),\n  ])\n  .and(baseShape);\n\nconst requestShape = z.object({\n  page: z.number(),\n  results: z.array(resultShape),\n  total_pages: z.number(),\n  total_results: z.number(),\n});\n```\n\n```text\nz.discriminatedUnion()\n```\n\n```text\nresults\n```\n\n```text\nbaseShape\n```\n\n========================================\n\nComments:\n- You are the GOAT! Thank you for taking the time to answer so thoroughly","metadata":{"transformedAt":"2026-08-18T18:33:48.866Z","totalAnswersIncluded":0,"totalCodeBlocksIncluded":28,"totalLines":359,"estimatedTokens":2146}}26{"id":"stack-73281501","source":"stackoverflow","questionId":73281501,"title":"At least one / minimum one field in Zod Schema Validation","tags":["node.js","typescript","mongodb","joi","zod"],"text":"Title: At least one / minimum one field in Zod Schema Validation\nTags: node.js, typescript, mongodb, joi, zod\nSource: Stack Overflow\n\nQuestion:\nI have implemented this code using JOI where the user has to send the userId and at least one of the keys from the body. How to implement the same using ZOD ??\n\n```\nparams: Joi.object().keys({\n userId: Joi.required().custom(objectId),\n }),\n body: Joi.object()\n .keys({\n name: Joi.string(),\n email: Joi.string().email(),\n password: Joi.string().custom(password),\n })\n .min(1),\n};\n```\n\n========================================\n\nTop Answer:\nYou may check this schema that will handle MongoDB id and custom password validation:\n\n```\nimport mongoose from 'mongoose'\nimport { z } from 'zod'\n\nconst schema = z\n .object({\n params: z.object({\n userId: z.custom(),\n }),\n body: z.object({\n name: z.string(),\n email: z.string().email(),\n password: z\n .string()\n .min(2, 'password should have at least 2 alphabets')\n .max(20, 'password should be no longer than 20 alphabets')\n .refine((value) => /[a-zA-Z]/.test(value), 'password should contain only alphabets')\n }),\n })\n .strict()\n```\n\n========================================\n\nCode:\n```text\nparams: Joi.object().keys({\n    userId: Joi.required().custom(objectId),\n  }),\n  body: Joi.object()\n    .keys({\n      name: Joi.string(),\n      email: Joi.string().email(),\n      password: Joi.string().custom(password),\n    })\n    .min(1),\n};\n```\n\n```js\nconst schema = z.object({\n  params: z.object({\n    userId: z.string()\n  }),\n  body: z\n    .object({\n      name: z.string(),\n      email: z.string().email(),\n      password: z.string()\n    })\n    .partial()\n    .refine(\n      ({ name, email, password }) =>\n        name !== undefined || email !== undefined || password !== undefined,\n      { message: \"One of the fields must be defined\" }\n    )\n});\n```\n\n```js\nconst atLeastOneDefined = (obj: Record<string | number | symbol, unknown>) =>\n  Object.values(obj).some(v => v !== undefined);\n```\n\n```text\nzod\n```\n\n```text\nrefine\n```\n\n```text\nsuperRefine\n```\n\n```text\nZodError\n```\n\n```text\nrefine\n```\n\n```js\nimport mongoose from 'mongoose'\nimport { z } from 'zod'\n\nconst schema = z\n  .object({\n    params: z.object({\n      userId: z.custom<mongoose.Types.ObjectId>(),\n    }),\n    body: z.object({\n      name: z.string(),\n      email: z.string().email(),\n      password: z\n        .string()\n        .min(2, 'password should have at least 2 alphabets')\n        .max(20, 'password should be no longer than 20 alphabets')\n        .refine((value) => /[a-zA-Z]/.test(value), 'password should contain only alphabets')\n     }),\n   })\n    .strict()\n```\n\n========================================\n\nComments:\n- Isn't it enough to do `Object.keys(obj).length > 0` in that function?","metadata":{"transformedAt":"2026-08-18T18:33:48.866Z","totalAnswersIncluded":1,"totalCodeBlocksIncluded":9,"totalLines":136,"estimatedTokens":685}}27{"id":"stack-76878664","source":"stackoverflow","questionId":76878664,"title":"React hook form and zod inumber input","tags":["reactjs","react-hook-form","zod"],"text":"Title: React hook form and zod inumber input\nTags: reactjs, react-hook-form, zod\nSource: Stack Overflow\n\nQuestion:\nI have created a form with react hook form and did a validation with zod. In one input I want to write in numbers, when I write any number, the error says it is not a number:\n\n```\n (\n \n )}\n```\n\n```\ncalories: z\n .number({\n required_error: \"Calories is required\",\n invalid_type_error: \"Calories must be a number\",\n })\n .int()\n .positive()\n .min(1, { message: \"Calories should be at least 1\" }),\n```\n\nI am missing something?\n\nDid not find any solution to this\n\n========================================\n\nTop Answer:\nwhat you want is:\n\n```\ncalories: z.coerce\n .number({\n required_error: \"Calories is required\",\n invalid_type_error: \"Calories must be a number\",\n })\n .int()\n .positive()\n .min(1, { message: \"Calories should be at least 1\" }),\n```\n\nnote the `coerce` before the `.number()`. It will take whatever it is inputted, i.e.: the string `'42'` and will cast it to the number `42`.\n\n========================================\n\nCode:\n```text\n<Controller\n          name=\"calories\"\n          control={control}\n          defaultValue={1}\n          render={({ field }) => (\n            <input\n              {...field}\n              type=\"number\"\n              className=\"w-full px-3 py-2 border rounded-md\"\n            />\n          )}\n```\n\n```text\ncalories: z\n    .number({\n      required_error: \"Calories is required\",\n      invalid_type_error: \"Calories must be a number\",\n    })\n    .int()\n    .positive()\n    .min(1, { message: \"Calories should be at least 1\" }),\n```\n\n```text\ncalories: z.preprocess(\n(a) => parseInt(z.string().parse(a), 10),\nz.number().positive().min(1)\n),\n```\n\n```text\nnumber\n```\n\n```text\nstring\n```\n\n```text\nstring\n```\n\n```text\nnumber()\n```\n\n```text\n<input\n      {...register('numberInput', {\n        setValueAs: (value) => Number(value),\n      })}\n      type=\"number\"\n    />\n```\n\n```text\ncalories: z.coerce\n    .number({\n      required_error: \"Calories is required\",\n      invalid_type_error: \"Calories must be a number\",\n    })\n    .int()\n    .positive()\n    .min(1, { message: \"Calories should be at least 1\" }),\n```\n\n```text\ncoerce\n```\n\n```text\n.number()\n```\n\n```text\n'42'\n```\n\n```text\n42\n```\n\n```text\nvalueAsNumber:true\n```\n\n========================================\n\nComments:\n- The problem with this is it allows empty string if you use min(0)\n- This answer relies on the fact `\"\"` (empty string) will be coerced into 0, so `min(1)` would error when it gets 0. This answer doesn't help us allow `0` but prevent `\"\"`. If anyone finds a solution for that, let me know.\n- `valueAsNumber` is only available for `register` function, not in `controller` or `useController`","metadata":{"transformedAt":"2026-08-18T18:33:48.866Z","totalAnswersIncluded":1,"totalCodeBlocksIncluded":14,"totalLines":143,"estimatedTokens":677}}28{"id":"stack-72768172","source":"stackoverflow","questionId":72768172,"title":"Zod: Create a primitive object from defaults","tags":["javascript","json","zod"],"text":"Title: Zod: Create a primitive object from defaults\nTags: javascript, json, zod\nSource: Stack Overflow\n\nQuestion:\nI'm pretty sure this exists, but I haven't been able to find anything about it despite some digging. Say that I have a `zod` Schema like such:\n\n```\nconst Person = zod.object({\n name: z.string().default(''),\n age: z.number().nullable();\n});\n```\n\nIs there a way to create something like this:\n\n```\nconst InstancePerson = {\n name: '',\n age: null\n}\n```\n\nfrom the `zod` Schema?\n\n========================================\n\nTop Answer:\nThere doesn't seem to be a direct way to do this sort of thing from the library, but you can dig into their `_` private fields and get the functionality you're looking for.\n\nThere are some risks associated with this approach because library maintainers typically don't guarantee stability in these private properties. If you're relying on this behavior you may need to be extra careful about version bumps.\n\nOk disclaimer out of the way, something like this is possible. Extending this to more types is left as an exercise for the reader:\n\n```\nimport { z } from \"zod\";\n\nconst schema = z.object({\n name: z.string(),\n age: z.number().nullable()\n});\n\nconst schemaDefaults = (\n schema: Schema\n): z.TypeOf => {\n switch (schema._def.typeName) {\n case z.ZodFirstPartyTypeKind.ZodDefault:\n return schema._def.defaultValue();\n case z.ZodFirstPartyTypeKind.ZodObject: {\n // The switch wasn't able to infer this but the cast should\n // be safe.\n return Object.fromEntries(\n Object.entries(\n (schema as z.SomeZodObject).shape\n ).map(([key, value]) => [key, schemaDefaults(value)])\n );\n }\n case z.ZodFirstPartyTypeKind.ZodString:\n return \"\";\n case z.ZodFirstPartyTypeKind.ZodNull:\n return null;\n case z.ZodFirstPartyTypeKind.ZodNullable:\n return null;\n // etc\n default:\n throw new Error(`Unsupported type ${schema._type}`);\n }\n};\n\nconsole.log(schemaDefaults(schema));\n```\n\nHere, I've specified no defaults but the code still outputs what you expected. If you specified \"foo\" as the default for `name` the code will output `{ name: \"foo\", age: null }`\n\nA shorter approach would be to simply dig in one layer into the `_def` of your schema looking for `defaultValue` functions to call, but I think the given approach is more principled since it could be extended to support every core `zod` schema type.\n\nOne last word of warning, some of the `zod` types are not as straightforward to handle as others. Something like `z.number` could be reasonably given a default of `0`, but `z.union` or `z.intersection` would have interesting recursive cases.\n\nIt might be worth building out a library just for this handling or else opening an issue with the repo to make it part of the offered api.\n\n========================================\n\nCode:\n```js\nconst Person = zod.object({\n    name: z.string().default(''),\n    age: z.number().nullable();\n});\n```\n\n```js\nconst InstancePerson = {\n    name: '',\n    age: null\n}\n```\n\n```text\nzod\n```\n\n```text\nzod\n```\n\n```js\nconst Person = zod.object({\n    name: z.string().default(''),\n    age: z.number().nullable().default(null)\n}).default({}); // .default({}) could be omitted in this case but should be set in nested objects\n```\n\n```text\nconst InstancePerson = Person.parse({});\n```\n\n```text\nzod\n```\n\n```text\nimport { z } from \"zod\";\n\nconst schema = z.object({\n  name: z.string(),\n  age: z.number().nullable()\n});\n\nconst schemaDefaults = <Schema extends z.ZodFirstPartySchemaTypes>(\n  schema: Schema\n): z.TypeOf<Schema> => {\n  switch (schema._def.typeName) {\n    case z.ZodFirstPartyTypeKind.ZodDefault:\n      return schema._def.defaultValue();\n    case z.ZodFirstPartyTypeKind.ZodObject: {\n      // The switch wasn't able to infer this but the cast should\n      // be safe.\n      return Object.fromEntries(\n        Object.entries(\n          (schema as z.SomeZodObject).shape\n        ).map(([key, value]) => [key, schemaDefaults(value)])\n      );\n    }\n    case z.ZodFirstPartyTypeKind.ZodString:\n      return \"\";\n    case z.ZodFirstPartyTypeKind.ZodNull:\n      return null;\n    case z.ZodFirstPartyTypeKind.ZodNullable:\n      return null;\n    // etc\n    default:\n      throw new Error(`Unsupported type ${schema._type}`);\n  }\n};\n\nconsole.log(schemaDefaults(schema));\n```\n\n```text\n_\n```\n\n```text\nname\n```\n\n```text\n{ name: \"foo\", age: null }\n```\n\n```text\n_def\n```\n\n```text\ndefaultValue\n```\n\n```text\nzod\n```\n\n```text\nzod\n```\n\n```text\nz.number\n```\n\n```text\n0\n```\n\n```text\nz.union\n```\n\n```text\nz.intersection\n```\n\n```js\nconst Model = z.object({\n    title: z.string(),\n    active: z.boolean().default(false)\n})\n\ntype ModelOutput = z.infer<typeof Model>\n// ^ type ModelOutput = {\n//    title: string;\n//    active: boolean;\n//}\n\ntype ModelInput = z.input<typeof Model>\n// ^ type ModelInput = {\n//    title: string;\n//    active?: boolean | undefined; // << DEFAULT\n// }\n```\n\n```js\nconst makeInstantiator =\n  <T extends z.ZodType<any>>(model: T) =>\n  (input: z.input<T>): z.output<T> => {\n    return model.parse(input);\n  };\n\nconst instantiateModel = makeInstantiator(Model);\n// const instantiateModel: (input: {\n//   title: string;\n//   active?: boolean | undefined;\n// }) => {\n//   title: string;\n//   active: boolean;\n// }\n```\n\n```text\n.parse\n```\n\n```text\nunknown\n```\n\n```text\nMyZodObject.createInstance\n```\n\n```text\nz.input<typeof MyShape>\n```\n\n```text\n.default\n```\n\n```text\ntype ExtractedDefaults<T> = {\n  [P in keyof T]?: T[P] extends ZodTypeAny ? ReturnType<T[P][\"parse\"]> : never;\n};\n\nexport function extractDefaults<TSchema extends ZodRawShape>(\n  schema: z.ZodObject<TSchema>,\n): ExtractedDefaults<TSchema> {\n  const schemaShape = schema.shape;\n  const result = {} as ExtractedDefaults<TSchema>;\n\n  for (const key in schemaShape) {\n    const fieldSchema = schemaShape[key];\n    result[key as keyof TSchema] = extractValueFromSchema(\n      fieldSchema!,\n    ) as ExtractedDefaults<TSchema>[keyof TSchema];\n  }\n\n  return result;\n}\n\nfunction extractValueFromSchema<T extends ZodTypeAny>(fieldSchema: T): unknown {\n  if (fieldSchema instanceof z.ZodDefault) {\n    return (\n      fieldSchema._def as { defaultValue: () => unknown }\n    ).defaultValue() as ReturnType<T[\"parse\"]>;\n  } else if (fieldSchema instanceof z.ZodObject) {\n    return extractDefaultsForm(fieldSchema);\n  } else if (fieldSchema instanceof z.ZodArray) {\n    return BASE_DEFAULTS.ARRAY.slice();\n  } else {\n    return handleBaseTypes(fieldSchema);\n  }\n}\n\nfunction handleBaseTypes<T extends ZodTypeAny>(fieldSchema: T): unknown {\n  switch (fieldSchema.constructor) {\n    case z.ZodString:\n      return BASE_DEFAULTS.STRING;\n    case z.ZodDate:\n      return BASE_DEFAULTS.STRING;\n    case z.ZodNumber:\n      return BASE_DEFAULTS.NUMBER;\n    case z.ZodBoolean:\n      return BASE_DEFAULTS.BOOLEAN;\n    case z.ZodNull:\n      return BASE_DEFAULTS.NULL;\n    case z.ZodNullable:\n      return BASE_DEFAULTS.NULL;\n    case z.ZodOptional:\n      return BASE_DEFAULTS.UNDEFINED; // Choose appropriately between UNDEFINED or NULL\n    default:\n      return handleTransformedTypes(fieldSchema);\n  }\n}\n\nfunction handleTransformedTypes<T extends ZodTypeAny>(fieldSchema: T): unknown {\n  if (\n    fieldSchema instanceof z.ZodTransformer &&\n    (fieldSchema._def as { innerType: ZodTypeAny }).innerType\n  ) {\n    return extractValueFromSchema(\n      (fieldSchema._def as { innerType: ZodTypeAny }).innerType,\n    );\n  }\n  return BASE_DEFAULTS.UNDEFINED;\n}\n```\n\n```text\nexport const BASE_DEFAULTS = {\n  STRING: \"\",\n  NUMBER: 0,\n  BOOLEAN: false,\n  DATE: getTodayPlusTime(), // today date object\n  OBJECT: {}, // consider if this is best...\n  ARRAY: [],\n  NULL: null,\n  UNDEFINED: undefined,\n};\n\nconst BASE_DEFAULTS_FORM = {\n  STRING: \"\",\n  NUMBER: null,\n  BOOLEAN: false,\n  DATE: getTodayPlusTimeDateString(), // today string (specific format)\n  OBJECT: {}, // consider if this is best...\n  ARRAY: [],\n  NULL: null,\n  UNDEFINED: null, // consider if this is best...\n};\n```\n\n```text\nexport const schemaCreate = z.object(...)\nexport const TDocCreate = z.infer(typeof schemaCreate)\n\nexport const DEFAULT_VALUES = extractDefaults(\n  schemaCreate,\n) as unknown as TDocCreate;\n```\n\n```text\n.parse({})\n```\n\n```text\n(fieldSchema._def as ...)\n```\n\n```text\nz.object(..)\n```\n\n```text\nz..default(..)\n```\n\n```text\nz.number()\n```\n\n```text\nz.string()\n```\n\n```text\nBASE_DEFAULTS\n```\n\n```text\nz.refine(..)\n```\n\n```text\nz.coerce(..)\n```\n\n```text\nz.ZodTransformationType<z.ZodInnerTypeIsLocatedHere?, ...>\n```\n\n```ts\nimport { object, string, number, type input, type output } from \"zod\";\n\n/**\n * 1. Define sub-schemas.\n * Schema 'A' has no defaults, so it remains strictly required.\n * Schema 'B' provides defaults for all its fields.\n */\nconst A = object({ \n  A1: string(), \n  A2: number() \n});\n\nconst B = object({ \n  B1: string().default(\"1\"), \n  B2: number().default(2) \n});\n\n/**\n * 2. Define the parent schema.\n * By setting the default to 'B.parse({})', we are pre-hydrating the object.\n * This ensures that if the 'B' key is missing from the input, Zod receives\n * a complete object { B1: \"1\", B2: 2 } rather than just an empty {}.\n */\nconst C = object({ \n  A: A, \n  B: B.default(B.parse({})) \n});\n\n/**\n * 3. Testing the output.\n * We only provide the strictly required fields for 'A'.\n * Because of the self-parsing default, 'B' will be fully populated.\n */\nconst P = C.parse({ \n  A: { A1: \"1\", A2: 2 } \n});\n\nconsole.log(P); \n// Output: { A: { A1: \"1\", A2: 2 }, B: { B1: \"1\", B2: 2 } }\n\n/**\n * 4. Type Accuracy.\n * CInput: The 'B' key is optional (due to .default).\n * COutput: The 'B' key is required and guaranteed to be fully populated.\n */\ntype CInput = input<typeof C>;   \ntype COutput = output<typeof C>;\n```\n\n```text\n.default({})\n```\n\n```text\nschema.parse({})\n```\n\n========================================\n\nComments:\n- Pretty impractical due to the limitations for unions & intersections, but still a solution. Thanks for the effort.\n- I am really struggling here. Not only the unions, intersections, but also arrays and it especially does not work if you specify extra zod functions after an object like z.object({name: z.string, age: z.number}).describe('user'), the 'describe' is last zod object referred to and not not the upper zod object, so the recursion of the zod object only works without extra piped zod functions. Would it be a good idea to try to detect the actual top level ...def.innerType and then start testing what datatype actually needs to be generated?\n- Yeah that's what's rough about this approach. You'll essentially need to handle each type of zod object that can arise which means you'll need to be in lock step with the library and aware of the functions. I would say, unless you yourself are trying to make a library to handle this generically for anyone using zod, I would implement these features a la carte and throw in unimplemented cases to keep your sanity. What you're describing sounds like a viable option (but entails work)\n- Your solution is perfect for simple DTOs. I just added cases handlers for numbers, boolean, date and array. It helped me reducing code for creating default values for forms.\n- This don't work with validation rules. How to do this while avoiding them?\n- Also this does throw errors when there is a non-default value, and Person.parse does not type the input.\n- Can't you just use `model.decode`?","metadata":{"transformedAt":"2026-08-18T18:33:48.866Z","totalAnswersIncluded":1,"totalCodeBlocksIncluded":42,"totalLines":468,"estimatedTokens":2815}}29{"id":"stack-73043223","source":"stackoverflow","questionId":73043223,"title":"Infer type from key of object inside an array Zod","tags":["arrays","typescript","zod","trpc.io"],"text":"Title: Infer type from key of object inside an array Zod\nTags: arrays, typescript, zod, trpc.io\nSource: Stack Overflow\n\nQuestion:\nSo I'd like to grab the type from a key of an object within an array in Zod. That array is also nested within an object, just to make things extra difficult.\n\nThis is an abstract view of the problem I'm having:\n\n```\nconst obj = z.object({\n nestedArray: z.array(z.object({ valueIWant: z.string() }))\n})\n\n// Should be of type z.ZodArray() now, but still is of type z.ZodObject\nconst arrayOfObjs = obj.pick({ nestedArray: true })\n\n// Grab value in array through z.ZodArray().element\narrayOfObjs.element.pick({ valueIWant: true })\n```\n\nWhat should happen using arrays in Zod:\n\n```\n// Type of z.ZodArray\nconst arr = z.array(z.object({ valueIWant: z.string() }))\n\nconst myValue = arr.element.pick({ valueIWant: true })\n```\n\nHere is my actual problem:\n\nI have an API which returns the following object:\n\n```\nexport const wordAPI = z.object({\n words: z.array(\n z.object({\n id: z.string(),\n word: z.string(),\n translation: z.string(),\n type: z.enum(['verb', 'adjective', 'noun'])\n })\n )\n})\n```\n\nIn my tRPC input, I would like to allow filtering by word type. Right now, I've had to rewrite `z.enum(['verb', 'adjective', 'noun'])`, which isn't great as it could introduce problems later on. How can I infer the type of the word through the array?\n\ntRPC endpoint:\n\n```\nexport const translationsRouter = createRouter().query('get', {\n input: z.object({\n limit: z.number().default(10),\n avoid: z.array(z.string()).nullish(),\n wordType: z.enum(['verb', 'adjective', 'noun']).nullish() // <-- infer here\n }),\n [...]\n})\n```\n\n========================================\n\nCode:\n```js\nconst obj = z.object({\n  nestedArray: z.array(z.object({ valueIWant: z.string() }))\n})\n\n// Should be of type z.ZodArray() now, but still is of type z.ZodObject\nconst arrayOfObjs = obj.pick({ nestedArray: true })\n\n// Grab value in array through z.ZodArray().element\narrayOfObjs.element.pick({ valueIWant: true })\n```\n\n```js\n// Type of z.ZodArray\nconst arr = z.array(z.object({ valueIWant: z.string() }))\n\nconst myValue = arr.element.pick({ valueIWant: true })\n```\n\n```js\nexport const wordAPI = z.object({\n  words: z.array(\n    z.object({\n      id: z.string(),\n      word: z.string(),\n      translation: z.string(),\n      type: z.enum(['verb', 'adjective', 'noun'])\n    })\n  )\n})\n```\n\n```js\nexport const translationsRouter = createRouter().query('get', {\n  input: z.object({\n    limit: z.number().default(10),\n    avoid: z.array(z.string()).nullish(),\n    wordType: z.enum(['verb', 'adjective', 'noun']).nullish() // <-- infer here\n  }),\n  [...]\n})\n```\n\n```text\nz.enum(['verb', 'adjective', 'noun'])\n```\n\n```js\nconst wordTypeSchema = z.enum([\"verb\", \"adjective\", \"noun\"]);\ntype WordType = z.infer<typeof wordTypeSchema>;\nexport const wordAPI = z.object({\n  words: z.array(\n    z.object({\n      id: z.string(),\n      word: z.string(),\n      translation: z.string(),\n      type: wordTypeSchema\n    })\n  )\n});\n```\n\n```js\ntype WordAPI = z.infer<typeof wordAPI>;\ntype WordType = WordAPI['words'][number]['type'];\n//    ^- This will include `| null` because you used `.nullable`\n// If you don't want the | null you would need to say\ntype WordTypeNotNull = Exclude<WordType, null>;\n```\n\n```text\nwordType\n```\n\n```text\nz.object\n```\n\n```text\nWordType\n```\n\n========================================\n\nComments:\n- I thought it'll have been better to infer the type the complicated way, but I do it the way you recommended. ty :)\n- there is no `z.TypeOf` in the current version (3.21.4) of the lib\n- Interesting, I wonder why they took it out. I updated my answer to use `z.infer` which was the other option","metadata":{"transformedAt":"2026-08-18T18:33:48.866Z","totalAnswersIncluded":0,"totalCodeBlocksIncluded":10,"totalLines":153,"estimatedTokens":921}}30{"id":"stack-71450455","source":"stackoverflow","questionId":71450455,"title":"how to use zod with validator.js","tags":["javascript","zod","validator.js"],"text":"Title: how to use zod with validator.js\nTags: javascript, zod, validator.js\nSource: Stack Overflow\n\nQuestion:\nI have an application using zod but I'd like to use some methods from a different library (validator.js) zod documentation says:\n\nCheck out validator.js for a bunch of other useful string validation functions.\n\nNot sure if that means this functions are implemented on zod, or I have to also install validator.js, in that other case how I can use both libraries together? cant find any example.\n\nThanks!\n\n========================================\n\nCode:\n```js\nimport { z } from \"zod\";\nimport isCreditCard  from \"validator/lib/isCreditCard\";\n\nconst userSchema = z.object({\n  name: z.string(),\n  creditCard: z.string().refine(isCreditCard, {\n    message: 'Must be a valid credit card number'\n  }),\n})\n\nconsole.log(userSchema.safeParse({\n  name: 'Doug',\n  creditCard: '1234',\n}));\n\nconsole.log(userSchema.safeParse({\n  name: 'steve',\n  creditCard: '4000 0200 0000 0000'\n}));\n```\n\n```text\nvalidator.js\n```\n\n```text\nZodError\n```\n\n========================================\n\nComments:\n- Thanks! , they should add this to their docs. I will create the issue","metadata":{"transformedAt":"2026-08-18T18:33:48.866Z","totalAnswersIncluded":0,"totalCodeBlocksIncluded":3,"totalLines":50,"estimatedTokens":289}}31{"id":"stack-76646728","source":"stackoverflow","questionId":76646728,"title":"Testing fail with react-hook-form and zod","tags":["react-testing-library","react-hook-form","zod"],"text":"Title: Testing fail with react-hook-form and zod\nTags: react-testing-library, react-hook-form, zod\nSource: Stack Overflow\n\nQuestion:\nI'm trying to test a simple form built with react-hook-form and zod.\n\nMy form has 2 fields: email and password. It's basiclly the same as the example on the docs, except that I use zod to validate form field instead of passing options into `register` function. My test is quite simple as well, just click the button and expect to receive 2 `alert` on the DOM. But somehow it fail.\n\nHere is the form component:\n\n```\nimport { zodResolver } from '@hookform/resolvers/zod'\nimport { useForm } from 'react-hook-form'\nimport { z } from 'zod'\n\nconst formSchema = z.object({\n email: z.string().email(),\n password: z.string(),\n})\n\ntype Input = z.infer\n\nexport function SimpleForm() {\n const {\n register,\n handleSubmit,\n formState: { errors },\n } = useForm({ resolver: zodResolver(formSchema) })\n\n function onSubmit() {}\n\n return (\n \n email\n \n {errors.email && {errors.email.message}}\n password\n \n {errors.password && {errors.password.message}}\n SUBMIT\n \n )\n}\n```\n\nHere is the test file:\n\n```\nimport { SimpleForm } from './simple-form'\nimport { render, screen } from '@testing-library/react'\nimport userEvent from '@testing-library/user-event'\nimport React from 'react'\n\ndescribe('SimpleForm', () => {\n it('should display required error when value is invalid', async () => {\n render()\n\n const user = userEvent.setup()\n\n await user.click(screen.getByRole('button'))\n\n expect(await screen.findAllByRole('alert')).toHaveLength(2)\n })\n})\n```\n\nand the error:\n\n```\nSimpleForm › should display required error when value is invalid \n\n Unable to find role=\"alert\"\n\n Ignored nodes: comments, script, style\n \n \n \n \n email\n \n \n \n password\n \n \n \n SUBMIT\n \n \n \n \n\n 12 | await user.click(screen.getByRole('button'))\n 13 |\n > 14 | expect(await screen.findAllByRole('alert')).toHaveLength(2)\n | ^\n 15 | })\n 16 | })\n 17 |\n```\n\n========================================\n\nCode:\n```js\nimport { zodResolver } from '@hookform/resolvers/zod'\nimport { useForm } from 'react-hook-form'\nimport { z } from 'zod'\n\nconst formSchema = z.object({\n  email: z.string().email(),\n  password: z.string(),\n})\n\ntype Input = z.infer<typeof formSchema>\n\nexport function SimpleForm() {\n  const {\n    register,\n    handleSubmit,\n    formState: { errors },\n  } = useForm<Input>({ resolver: zodResolver(formSchema) })\n\n  function onSubmit() {}\n\n  return (\n    <form onSubmit={handleSubmit(onSubmit)}>\n      <label htmlFor='email'>email</label>\n      <input id='email' {...register('email')} type='email' />\n      {errors.email && <span role='alert'>{errors.email.message}</span>}\n      <label htmlFor='password'>password</label>\n      <input id='password' {...register('password')} type='password' />\n      {errors.password && <span role='alert'>{errors.password.message}</span>}\n      <button type='submit'>SUBMIT</button>\n    </form>\n  )\n}\n```\n\n```js\nimport { SimpleForm } from './simple-form'\nimport { render, screen } from '@testing-library/react'\nimport userEvent from '@testing-library/user-event'\nimport React from 'react'\n\ndescribe('SimpleForm', () => {\n  it('should display required error when value is invalid', async () => {\n    render(<SimpleForm />)\n\n    const user = userEvent.setup()\n\n    await user.click(screen.getByRole('button'))\n\n    expect(await screen.findAllByRole('alert')).toHaveLength(2)\n  })\n})\n```\n\n```bash\nSimpleForm › should display required error when value is invalid      \n\n    Unable to find role=\"alert\"\n\n    Ignored nodes: comments, script, style\n    <body>\n      <div>\n        <form>\n          <label\n            for=\"email\"\n          >\n            email\n          </label>\n          <input\n            id=\"email\"\n            name=\"email\"\n            type=\"email\"\n          />\n          <label\n            for=\"password\"\n          >\n            password\n          </label>\n          <input\n            id=\"password\"\n            name=\"password\"\n            type=\"password\"\n          />\n          <button\n            type=\"submit\"\n          >\n            SUBMIT\n          </button>\n        </form>\n      </div>\n    </body>\n\n      12 |     await user.click(screen.getByRole('button'))\n      13 |\n    > 14 |     expect(await screen.findAllByRole('alert')).toHaveLength(2)\n         |                         ^\n      15 |   })\n      16 | })\n      17 |\n```\n\n```text\nregister\n```\n\n```text\nalert\n```\n\n```js\nimport { render, screen, waitFor } from '@testing-library/react';\nimport userEvent from '@testing-library/user-event';\nimport { SimpleForm } from './test-form';\n\ndescribe('SimpleForm', () => {\n  it('should display required error when value is invalid', async () => {\n    render(<SimpleForm />);\n\n    const user = userEvent.setup();\n\n    await user.click(screen.getByRole('button'));\n\n    waitFor(() => {\n      const alerts = screen.getAllByRole('alert');\n      return expect(alerts.length).toBe(2);\n    });\n  });\n});\n```\n\n```text\nwaitFor\n```","metadata":{"transformedAt":"2026-08-18T18:33:48.867Z","totalAnswersIncluded":0,"totalCodeBlocksIncluded":7,"totalLines":238,"estimatedTokens":1238}}32{"id":"stack-75883100","source":"stackoverflow","questionId":75883100,"title":"How to make a custom error message in zod?","tags":["reactjs","typescript","forms","react-hook-form","zod"],"text":"Title: How to make a custom error message in zod?\nTags: reactjs, typescript, forms, react-hook-form, zod\nSource: Stack Overflow\n\nQuestion:\nI'm trying to write a custom error message for zod validation.\n\nThis is my schema object, which I passed in the error message.\n\n```\nconst schema: ZodType = z.object({\n firstName: z.string().nonempty(),\n lastName: z.string().nonempty(),\n email: z.string().email().min(5).nonempty(),\n pin: z.string( { invalid_type_error: \"Must contain 4 digitsss \"}).nonempty().min(4, \"Must be 4 digits\").max(4, \"Must be 4 digits\").regex(pinPattern),\n phoneNumber: z.string().nonempty().min(11),\n password: z.string().min(8).regex(Passwordregex).nonempty(),\n confirmPassword: z.string().min(8).nonempty(),\n }).refine(data => data.password === data.confirmPassword, {\n message: \"Passwords don't match\",\n path: ['confirmPassword']\n })\n```\n\nI've tried the string replace method, but I'm not getting my desired result.\n\n```\n{errors.\n{errors.firstName.message?.replace('String', 'First Name')}</}\n```\n\n========================================\n\nTop Answer:\nYou can use a custom message in zod by passing an object with the structure `{ message: \"Custom error message here\" }` as an argument.\n\nNote that in newer versions of Zod, `nonempty()` is deprecated, and you should instead use `min(1)` Source.\n\nIn your code above, to show an error that the First Name is required can be accomplished as follows:\n\n```\nconst schema: ZodType = z.object({\n firstName: z.string().min(1, { message: \"First Name is required\" })\n});\n```\n\nIf your field has a requirement for a minimum number of characters, you can chain a second `.min()` with the min number and respective error message if user enters less characters as the arguments.\n\n========================================\n\nCode:\n```js\nconst schema: ZodType<FormData> = z.object({\n    firstName: z.string().nonempty(),\n    lastName: z.string().nonempty(),\n    email: z.string().email().min(5).nonempty(),\n    pin: z.string( { invalid_type_error: \"Must contain 4 digitsss \"}).nonempty().min(4, \"Must be 4 digits\").max(4, \"Must be 4 digits\").regex(pinPattern),\n    phoneNumber: z.string().nonempty().min(11),\n    password: z.string().min(8).regex(Passwordregex).nonempty(),\n    confirmPassword: z.string().min(8).nonempty(),\n  }).refine(data => data.password === data.confirmPassword, {\n    message: \"Passwords don't match\",\n    path: ['confirmPassword']\n  })\n```\n\n```text\n{errors.\n<span className='text-xs font-medium text-[#DC2626]'>{errors.firstName.message?.replace('String', 'First Name')}</}\n```\n\n```text\nimport { ZodError, ZodIssue } from 'zod'\n\nconst formatZodIssue = (issue: ZodIssue): string => {\n    const { path, message } = issue\n    const pathString = path.join('.')\n\n    return `${pathString}: ${message}`\n}\n\n// Format the Zod error message with only the current error\nexport const formatZodError = (error: ZodError): string => {\n    const { issues } = error\n\n    if (issues.length) {\n        const currentIssue = issues[0]\n\n        return formatZodIssue(currentIssue)\n    }\n}\n```\n\n```text\ntry {\n      ...your code here  \n    } catch (error) {\n        console.error(error)\n        throw new Error(formatZodError(error))\n    }\n```\n\n```text\nconst schema: ZodType<FormData> = z.object({\n  firstName: z.string().min(1, { message: \"First Name is required\" })\n});\n```\n\n```text\n{  message: \"Custom error message here\" }\n```\n\n```text\nnonempty()\n```\n\n```text\nmin(1)\n```\n\n```text\n.min()\n```\n\n========================================\n\nComments:\n- Please clarify your specific problem or provide additional details to highlight exactly what you need. As it's currently written, it's hard to tell exactly what you're asking.\n- It's undeprecated","metadata":{"transformedAt":"2026-08-18T18:33:48.867Z","totalAnswersIncluded":1,"totalCodeBlocksIncluded":9,"totalLines":129,"estimatedTokens":925}}33{"id":"stack-77134910","source":"stackoverflow","questionId":77134910,"title":"How can I remove all whitespace in Zod?","tags":["javascript","typescript","zod"],"text":"Title: How can I remove all whitespace in Zod?\nTags: javascript, typescript, zod\nSource: Stack Overflow\n\nQuestion:\nAccording to the docs of Zod I can use trim, but trim will only remove the whitespace characters at the end and beginning. I am looking for a way to remove all of the whitespace characters. To give you an idea of the setup I am using (removed irrelevant code):\n\n```\nconst stp = zodString({\n invalid_type_error: '',\n required_error: '',\n}).trim()\n .min(1, { message: '' })\n .max(10, { message: '' })\n .regex(reg, { message: '', });\n```\n\nIs there a way to implement some sort of trim to remove all white space with zodString?\n\n========================================\n\nTop Answer:\nzod supports the `.trim()` transformation\n\ndocs\n\n```\nconst mySchema = z.object({ mykey: z.string().trim() })\n```\n\n========================================\n\nCode:\n```text\nconst stp = zodString({\n    invalid_type_error: '',\n    required_error: '',\n}).trim()\n    .min(1, { message: '' })\n    .max(10, { message: '' })\n    .regex(reg, { message: '', });\n```\n\n```text\nz.string().transform(value => value.replace(/\\s+/g, ''))\n.pipe(z.string().min(1, { message: 'This field is required' }))\n```\n\n```text\nz.string().transform(value => value.replaceAll(\" \", \"\"))\n```\n\n```text\n.trim()\n```\n\n```text\n.transform()\n```\n\n```text\nconst mySchema = z.object({ mykey: z.string().trim() })\n```\n\n```text\n.trim()\n```\n\n========================================\n\nComments:\n- \"Trimming space\" in the middle of a string is odd. Could you provide sample data demonstrating this? I can see compacting multiple spaces into one space.\n- Well for example, you just wrote \"Trimming space\". I wish to have the white character in between \"Trimming space\" removed.\n- Does this answer your question? Replace all whitespace characters\n- Wouldn't you just need `z.string().regex(&#47;^\\S+$&#47;);`\n- @isherwood No, because that would be done outside of the zodstring function. I am looking for a built-in way with zodString to resolve this.\n- @SouvikDey No, unfortunately it doesn;t.\n- Is this possible with zodString? I cannot change the setup.\n- \"transform is not a function\" whenever I use your answer.\n- What is `zodString`? where did you import from? there is a `ZodString` class with uppercase Z that returns a ZodString instance which includes `.transform`. What about `zodString`?\n- I changed the code to z.string as well. Still not capturing it. I can update the OP so you can see it for yourself. All I am looking for is the original post code (can even be with z.string) to have all the white characters removed.\n- `.transform` is a method for `z.string()` that takes a function as argument. this function takes a parameter (value: string) and must return the new/modified value.\n- I have: z.string().transfrom(value => value.replaceAll(\" \", \"\")) and it throws the error \"transform is not a function\". I imported z from zod as well. Do I need to import transform as well?\n- What is your zod version in `package.json`?\n- Let us continue this discussion in chat.\n- trim() does not remove whitespaces in the middle of the string, as asked by the question","metadata":{"transformedAt":"2026-08-18T18:33:48.867Z","totalAnswersIncluded":1,"totalCodeBlocksIncluded":7,"totalLines":86,"estimatedTokens":780}}34{"id":"stack-78083213","source":"stackoverflow","questionId":78083213,"title":"How can I make a field required based in other field value with Zod?","tags":["typescript","react-hook-form","zod"],"text":"Title: How can I make a field required based in other field value with Zod?\nTags: typescript, react-hook-form, zod\nSource: Stack Overflow\n\nQuestion:\nI'm trying to validate a form with Zod and react-hook-form, and I need to make some fields required based on the value of other field. Here is my schema:\n\n```\nconst formSchema = z.object({\n cli_rut: z.string(),\n cli_persona_natural: z.enum([\"SI\", \"NO\"]),\n cli_nombres: z.string().optional(),\n cli_apellido_paterno: z.string().optional(),\n cli_apellido_materno: z.string().optional(),\n cli_razon_social: z.string().optional(),\n cli_estado: z.string().default(\"ACTIVO\").optional(),\n});\n```\n\nin this case I need to make required cli_nombres, cli_apellido_materno, and cli_apellido_paterno if cli_persona_natural = \"SI\", any ideas of how can i do it? Thanks\n\nI'm expecting the fields to be required if cli_persona_natural is \"SI\"\n\n========================================\n\nCode:\n```text\nconst formSchema = z.object({\n    cli_rut: z.string(),\n    cli_persona_natural: z.enum([\"SI\", \"NO\"]),\n    cli_nombres: z.string().optional(),\n    cli_apellido_paterno: z.string().optional(),\n    cli_apellido_materno: z.string().optional(),\n    cli_razon_social: z.string().optional(),\n    cli_estado: z.string().default(\"ACTIVO\").optional(),\n});\n```\n\n```js\nconst formSchema = z\n  .object({\n    cli_rut: z.string(),\n    cli_persona_natural: z.enum([\"SI\", \"NO\"]),\n    cli_nombres: z.string().optional(),\n    cli_apellido_paterno: z.string().optional(),\n    cli_apellido_materno: z.string().optional(),\n    cli_razon_social: z.string().optional(),\n    cli_estado: z.string().default(\"ACTIVO\").optional(),\n  })\n  .superRefine((data, ctx) => {\n    if (data.cli_persona_natural === \"SI\") {\n      if (data.cli_nombres === undefined) {\n        // I took a best guess at the messages but it's not my native language\n        ctx.addIssue({\n          code: z.ZodIssueCode.custom,\n          message: \"El campo nombres es requerido\",\n        });\n      }\n      if (data.cli_apellido_paterno === undefined) {\n        ctx.addIssue({\n          code: z.ZodIssueCode.custom,\n          message: \"El campo apellido paterno es requerido\",\n        });\n      }\n      if (data.cli_apellido_materno === undefined) {\n        ctx.addIssue({\n          code: z.ZodIssueCode.custom,\n          message: \"El campo apellido materno es requerido\",\n        });\n      }\n    }\n  });\n```\n\n```text\nimport { z } from \"zod\";\n\nconst baseSchema = z.object({\n  cli_rut: z.string(),\n  cli_razon_social: z.string().optional(),\n  cli_estado: z.string().default(\"ACTIVO\").optional(),\n});\n\nconst personaNaturalSchema = z.object({\n  cli_persona_natural: z.literal(\"SI\"),\n  cli_nombres: z.string(),\n  cli_apellido_paterno: z.string(),\n  cli_apellido_materno: z.string(),\n});\n\n// Again no clue if this naming makes sense in practice\nconst personaJuridicaSchema = z.object({\n  cli_persona_natural: z.literal(\"NO\"),\n  cli_nombres: z.string().optional(),\n  cli_apellido_paterno: z.string().optional(),\n  cli_apellido_materno: z.string().optional(),\n});\n\nconst formSchema = z\n  .discriminatedUnion(\"cli_persona_natural\", [\n    personaNaturalSchema,\n    personaJuridicaSchema,\n  ])\n  .and(baseSchema);\n\nconsole.log(\n  formSchema.safeParse({\n    cli_persona_natural: \"SI\",\n    cli_rut: \"12345678\",\n    cli_nombres: \"John\",\n    cli_apellido_paterno: \"Steve\",\n    cli_apellido_materno: \"Tessa\",\n  })\n); // success\nconsole.log(\n  formSchema.safeParse({\n    cli_persona_natural: \"NO\",\n    cli_rut: \"12345678\",\n  })\n); // success\nconsole.log(\n  formSchema.safeParse({\n    cli_persona_natural: \"SI\",\n    cli_rut: \"12345678\",\n  })\n); // failure\n```\n\n```text\nsuperRefine\n```\n\n```text\ndiscriminatedUnion\n```\n\n```text\ncli_persona_natural\n```","metadata":{"transformedAt":"2026-08-18T18:33:48.867Z","totalAnswersIncluded":0,"totalCodeBlocksIncluded":6,"totalLines":139,"estimatedTokens":926}}35{"id":"stack-74100894","source":"stackoverflow","questionId":74100894,"title":"How to transform object to array before parsing in Zod","tags":["reactjs","typescript","integration","zod"],"text":"Title: How to transform object to array before parsing in Zod\nTags: reactjs, typescript, integration, zod\nSource: Stack Overflow\n\nQuestion:\nI do have an external URL endpoint that **returns an array of field object when it is more than 2 and an object when there is only one**, see the snippet below:\n\nReturn when the field count is one:\n\n```\n{\n \"fields\": { \"fullName\": \"fieldFullname\", \"type\": \"fieldType\" }\n}\n```\n\nReturn when the field is more than one:\n\n```\n{\n \"fields\": [\n { \"fullName\": \"fieldFullname\", \"type\": \"fieldType\" },\n { \"fullName\": \"fieldFullname\", \"type\": \"fieldType\" }\n ]\n}\n```\n\nCurrently, this is my schema using zod:\n\n```\nexport const sObjectMetadataSchema = z.object({\n fields: z.array(metadataFieldSchema).optional()\n});\n\nexport const metadataFieldSchema = z.object({\n fullName: z.string().optional(),\n type: z.string().optional(),\n});\n```\n\nIt is configured that it will only accept an array of objects. When it returns only one field it throws an error:\n\n```\n{\n \"code\": \"invalid_type\",\n \"expected\": \"array\",\n \"received\": \"object\",\n \"path\": [],\n \"message\": \"Expected array, received object\"\n}\n```\n\nMy goal is if it returns a single object it will convert it to an array of objects during runtime. Currently trying to implement using `transform` but still not working:\n\nAn initial implementation using transform:\n\n```\nexport const sObjectMetadataSchema = z.object({\nfields: z.unknown().transform((rel) => {\n return Array.isArray(rel)\n ? z.array(metadataFieldSchema).optional()\n : 'Convert the rel to Array?';\n }),\n});\n```\n\n========================================\n\nTop Answer:\nThanks for the answer @Konrad !\n\nI improved it a little bit in typescript, so it is also typed correctly:\n\n```\nconst arrayFromString = (schema: T) => {\n return z.preprocess((obj) => {\n if (Array.isArray(obj)) {\n return obj;\n } else if (typeof obj === \"string\") {\n return obj.split(\",\");\n } else {\n return [];\n }\n }, z.array(schema));\n};\n```\n\n========================================\n\nCode:\n```text\n{\n  \"fields\": { \"fullName\": \"fieldFullname\", \"type\": \"fieldType\" }\n}\n```\n\n```text\n{\n  \"fields\": [\n      { \"fullName\": \"fieldFullname\", \"type\": \"fieldType\" },\n      { \"fullName\": \"fieldFullname\", \"type\": \"fieldType\" }\n   ]\n}\n```\n\n```text\nexport const sObjectMetadataSchema = z.object({\n  fields: z.array(metadataFieldSchema).optional()\n});\n\nexport const metadataFieldSchema = z.object({\n  fullName: z.string().optional(),\n  type: z.string().optional(),\n});\n```\n\n```text\n{\n  \"code\": \"invalid_type\",\n  \"expected\": \"array\",\n  \"received\": \"object\",\n  \"path\": [],\n  \"message\": \"Expected array, received object\"\n}\n```\n\n```text\nexport const sObjectMetadataSchema = z.object({\nfields: z.unknown().transform((rel) => {\n    return Array.isArray(rel)\n        ? z.array(metadataFieldSchema).optional()\n        : 'Convert the rel to Array?';\n    }),\n});\n```\n\n```text\ntransform\n```\n\n```text\nconst FieldsSchema = z.object({\n  fullName: z.string(),\n  type: z.string()\n});\n\nexport const sObjectMetadataSchema = z.object({\nfields: z.union([FieldsSchema, FieldsSchema.array()]).transform((rel) => {\n    return Array.isArray(rel)\n        ? rel\n        : [rel];\n    }),\n});\n```\n\n```text\nconst arrayFromString = <T extends ZodTypeAny>(schema: T) => {\n  return z.preprocess((obj) => {\n    if (Array.isArray(obj)) {\n      return obj;\n    } else if (typeof obj === \"string\") {\n      return obj.split(\",\");\n    } else {\n      return [];\n    }\n  }, z.array(schema));\n};\n```\n\n```text\nexport const arrayOfStringsSchema = z\n   .union([z.record(z.string(), z.string()), z.string().array()])\n   .transform((rel) => {\n      return Array.isArray(rel) ? rel : Object.values(rel).flat();\n   });\n```\n\n========================================\n\nComments:\n- My god! you save my day @Konrad, It works perfectly. Thanks mate!\n- z.union returns a type that does not allow for further validations.\n- I'd add this is preferred not only for the TypeScript but because `preprocess` runs before validation occurs. As of `v3.22.2` the docs for preprocess mention \"But sometimes you want to apply some transform to the input before parsing happens. A common use case: type coercion. Zod enables this with the z.preprocess().\"","metadata":{"transformedAt":"2026-08-18T18:33:48.867Z","totalAnswersIncluded":1,"totalCodeBlocksIncluded":9,"totalLines":182,"estimatedTokens":1042}}36{"id":"stack-76123184","source":"stackoverflow","questionId":76123184,"title":"How to infer type from a schema generated by a generic function in zod?","tags":["typescript","generics","zod"],"text":"Title: How to infer type from a schema generated by a generic function in zod?\nTags: typescript, generics, zod\nSource: Stack Overflow\n\nQuestion:\nI have a generic function which generated a very simple schema.\n\n```\nconst LeafSchema = (valueSchema: T) { \n return z.object({ value: valueSchema })\n}\n```\n\nNow I want to infer the type of this generated Schema, with using ReturnType, but also I have to use a generic, if not value will be `any`.\n\n```\ntype Leaf = z.infer>>\nconst getLeafValue = (leaf: Leaf) => leaf.value\n```\n\nHowever, I still get `any` when calling getLeafValue with `{ 'value': 123 }`. I understand that something wrong with my generics, but i'm not sure how to fix it. Sadly I haven't found much about generics with zod...\n\nHeres the Playground\n\n========================================\n\nTop Answer:\n```\nimport { z } from 'zod'\n\nconst LeafSchema = (valueSchema: T) => z.object({ value: valueSchema })\n\nconst LeafRefSchema = LeafSchema(z.string())\n\ntype LeafefSchemaInterface = z.infer\n```\n\n========================================\n\nCode:\n```text\nconst LeafSchema = <T extends z.ZodTypeAny>(valueSchema: T) { \n    return z.object({ value: valueSchema })\n}\n```\n\n```text\ntype Leaf<T extends z.ZodTypeAny> = z.infer<ReturnType<typeof LeafSchema<T>>>\nconst getLeafValue = <T extends z.ZodTypeAny>(leaf: Leaf<T>) => leaf.value\n```\n\n```text\nany\n```\n\n```text\nany\n```\n\n```text\n{ 'value': 123 }\n```\n\n```text\ntype Leaf<T> = z.infer<ReturnType<typeof LeafSchema<z.ZodType<T>>>>\ntype NumberLeaf = Leaf<number>\n//    ^? { value: number }\n\nconst getLeafValue = <T>(leaf: Leaf<T>) => leaf.value\nconst test = { 'value': 123 }\nconst val = getLeafValue(test)\n//     ^? { value: number | undefined }\n```\n\n```text\n<T>\n```\n\n```text\nZodType<T>\n```\n\n```text\n<T extends ZodAnyType>\n```\n\n```text\n<T>\n```\n\n```text\ngetLeafValue\n```\n\n```text\nz.infer\n```\n\n```text\nRequired<>\n```\n\n```text\nimport { z } from 'zod'\n\nconst LeafSchema = <T extends z.ZodTypeAny>(valueSchema: T) => z.object({ value: valueSchema })\n\nconst LeafRefSchema = LeafSchema(z.string())\n\ntype LeafefSchemaInterface = z.infer<typeof LeafRefSchema>\n```\n\n========================================\n\nComments:\n- Am I missing something or can't you just assert non-null? tsplay.dev/NB8G4W\n- Works for this case, but `{ value: undefined }` or `{ value: null }` would return `never` instead of `undefined` or `null`.","metadata":{"transformedAt":"2026-08-18T18:33:48.867Z","totalAnswersIncluded":1,"totalCodeBlocksIncluded":14,"totalLines":117,"estimatedTokens":590}}37{"id":"stack-73106592","source":"stackoverflow","questionId":73106592,"title":"Add fluent extension method to 3rd party class","tags":["typescript","extension-methods","zod"],"text":"Title: Add fluent extension method to 3rd party class\nTags: typescript, extension-methods, zod\nSource: Stack Overflow\n\nQuestion:\nI'm using `zod` which allows to define some validation rules using fluent function.\n\nEspecially, one of the functionis `optional` which allows to declare a field as optional. Unfortunately, this function does not accept a flag to enable/disable the optional behavior. In my case, the form is built dynamically and the optional flag must be defined at run time.\n\nI can create a small utility method to add this logic :\n\n```\nimport { z, ZodType} from 'zod';\n\nconst fieldIsRequired = true;\n\n// Method 1 : wrapper / Working\nconst makeOptional = (input : ZodType, required : boolean): ZodType => required ? input : input.optional();\n\nconst entry1 = makeOptional(\n z\n .string()\n .min(10)\n .max(100)\n , !fieldIsRequired\n);\n```\n\nThis is working well, but I lost the *fluent* code. Having one rule is acceptable, but adding more rules will leads to a hamburger of function call and parameters\n\nHow can I add a new fluent function to the zod type, which come from a 3rd party lib ?\n\nI've tried to implement extension methods, but I failed finding the correct syntax.\n\nHere's what I tried :\n\n```\nimport { z, ZodType} from 'zod';\n\nconst fieldIsRequired = true;\n\n// Method 2 : extension method / Not Working\n\ndeclare namespace zod {\n export abstract class ZodType {\n makeOptional: (required: boolean)=> ZodType;\n }\n}\n// Add syntaxic sugar to the Zod schema\nZodType.prototype.makeOptional = function (required: boolean): ZodType {\n return required ? this : this.optional();\n};\n\nconst entry2 = \n z\n .string()\n .min(10)\n .max(100)\n .makeOptional(!fieldIsRequired);\n```\n\nHow to fix this ?\n\nRepro : TS playground\n\n========================================\n\nCode:\n```js\nimport { z, ZodType} from 'zod';\n\nconst fieldIsRequired = true;\n\n// Method 1 : wrapper / Working\nconst makeOptional = (input : ZodType, required : boolean): ZodType => required ? input : input.optional();\n\nconst entry1 = makeOptional(\n    z\n    .string()\n    .min(10)\n    .max(100)\n    , !fieldIsRequired\n);\n```\n\n```js\nimport { z, ZodType} from 'zod';\n\nconst fieldIsRequired = true;\n\n// Method 2 : extension method / Not Working\n\ndeclare namespace zod {\n    export abstract class ZodType {\n        makeOptional: (required: boolean)=> ZodType;\n    }\n}\n// Add syntaxic sugar to the Zod schema\nZodType.prototype.makeOptional = function (required: boolean): ZodType {\n    return required ? this : this.optional();\n};\n\nconst entry2 =   \n  z\n    .string()\n    .min(10)\n    .max(100)\n    .makeOptional(!fieldIsRequired);\n```\n\n```text\nzod\n```\n\n```text\noptional\n```\n\n```js\nimport { z, ZodType } from 'zod';\n\nconst fieldIsRequired = true;\n\ndeclare module 'zod' {\n    export interface ZodType {\n        makeOptional: (required: boolean)=> ZodType;\n    }\n}\n// Add syntaxic sugar to the Zod schema\nz.ZodType.prototype.makeOptional = function (required: boolean): ZodType {\n    return required ? this : this.optional();\n};\n\nconst entry2 =   \n  z\n    .string()\n    .min(10)\n    .max(100)\n    .makeOptional(!fieldIsRequired);\n```\n\n```text\ndeclare module\n```\n\n```text\ndeclare namespace\n```\n\n```text\ndeclare module\n```","metadata":{"transformedAt":"2026-08-18T18:33:48.867Z","totalAnswersIncluded":0,"totalCodeBlocksIncluded":8,"totalLines":152,"estimatedTokens":795}}38{"id":"stack-77507221","source":"stackoverflow","questionId":77507221,"title":"Is there a way to get form values with onChange using Shadcn Form & Zod?","tags":["javascript","reactjs","typescript","forms","zod"],"text":"Title: Is there a way to get form values with onChange using Shadcn Form & Zod?\nTags: javascript, reactjs, typescript, forms, zod\nSource: Stack Overflow\n\nQuestion:\nI have implemented a form to sign in using zod for client-side validation. I wanted to also add a password strength display for which i decided to try out react-password-strength-bar.\n\nThe functionality is simple, you just render the PasswordStrengthBar and pass-in the password value as a prop:\n\n```\nimport PasswordStrengthBar from \"react-password-strength-bar\";\n\n```\n\nWhile trying so, I've noticed I cannot use onChange event listener for Input field, because apparently it is already used. Same goes with ref, where I would have used useEffect that would trigger every time the input value changes.\n\nI found that I can get the value using form.getValues(\"password\") it feels wrong to use form function as a dependency which I would then use as a value for PasswordStrengthBar. I have also tried placing form in useEffect, but it seems like it does not update with input change.\n\nDoes anyone have any ideas of how I could make this work?\n\nFull code:\n\n```\n\"use client\";\n\nimport { zodResolver } from \"@hookform/resolvers/zod\";\nimport * as z from \"zod\";\nimport { useForm } from \"react-hook-form\";\nimport { useContext, useEffect, useState } from \"react\";\nimport NotificationContext from \"@/lib/context/notification-context\";\nimport defaultNotification from \"@/lib/locale/default-notification\";\nimport PasswordStrengthBar from \"react-password-strength-bar\";\nimport { authFormSchema } from \"@/lib/formSchema\";\nimport { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from \"@/components/ui/form\";\nimport { Input } from \"@/components/ui/input\";\nimport SubmitButton from \"../ui/custom-ui/submit-btn\";\n\nexport default function AuthForm() {\n const notifCtx = useContext(NotificationContext);\n const [pass, setPass] = useState(\"\");\n\n const form = useForm>({\n resolver: zodResolver(authFormSchema),\n defaultValues: { email: \"\", password: \"\" }\n });\n const isLoading = form.formState.isSubmitting;\n\n async function onSubmit(values: z.infer) {\n // ✅ This will be type-safe and validated.\n notifCtx.setNotification(defaultNotification.pending);\n\n const res = await fetch(\"/api/auth/signup\", {\n method: \"POST\",\n body: JSON.stringify({ ...values })\n });\n const { err, msg } = await res.json();\n\n notifCtx.setNotification(defaultNotification[err ? \"error\" : \"success\"](msg));\n !err && form.reset();\n return;\n }\n useEffect(() => {\n setPass(form.getValues(\"password\"));\n }, [form]);\n\n return (\n \n \n (\n \n Email\n \n \n \n \n \n )}\n />\n (\n \n Password\n \n \n \n \n \n )}\n />\n\n \n\n \n \n \n \n \n );\n}\n```\n\n========================================\n\nCode:\n```js\nimport PasswordStrengthBar from \"react-password-strength-bar\";\n\n<PasswordStrengthBar password={pass} />\n```\n\n```js\n\"use client\";\n\nimport { zodResolver } from \"@hookform/resolvers/zod\";\nimport * as z from \"zod\";\nimport { useForm } from \"react-hook-form\";\nimport { useContext, useEffect, useState } from \"react\";\nimport NotificationContext from \"@/lib/context/notification-context\";\nimport defaultNotification from \"@/lib/locale/default-notification\";\nimport PasswordStrengthBar from \"react-password-strength-bar\";\nimport { authFormSchema } from \"@/lib/formSchema\";\nimport { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from \"@/components/ui/form\";\nimport { Input } from \"@/components/ui/input\";\nimport SubmitButton from \"../ui/custom-ui/submit-btn\";\n\nexport default function AuthForm() {\n  const notifCtx = useContext(NotificationContext);\n  const [pass, setPass] = useState<string>(\"\");\n\n  const form = useForm<z.infer<typeof authFormSchema>>({\n    resolver: zodResolver(authFormSchema),\n    defaultValues: { email: \"\", password: \"\" }\n  });\n  const isLoading = form.formState.isSubmitting;\n\n  async function onSubmit(values: z.infer<typeof authFormSchema>) {\n    // ✅ This will be type-safe and validated.\n    notifCtx.setNotification(defaultNotification.pending);\n\n    const res = await fetch(\"/api/auth/signup\", {\n      method: \"POST\",\n      body: JSON.stringify({ ...values })\n    });\n    const { err, msg } = await res.json();\n\n    notifCtx.setNotification(defaultNotification[err ? \"error\" : \"success\"](msg));\n    !err && form.reset();\n    return;\n  }\n  useEffect(() => {\n    setPass(form.getValues(\"password\"));\n  }, [form]);\n\n  return (\n    <Form {...form}>\n      <form onSubmit={form.handleSubmit(onSubmit)} className=\"space-y-2\">\n        <FormField\n          control={form.control}\n          name=\"email\"\n          render={({ field }) => (\n            <FormItem>\n              <FormLabel>Email</FormLabel>\n              <FormControl>\n                <Input placeholder=\"john@doe.com\" {...field} />\n              </FormControl>\n              <FormMessage />\n            </FormItem>\n          )}\n        />\n        <FormField\n          control={form.control}\n          name=\"password\"\n          render={({ field }) => (\n            <FormItem>\n              <FormLabel className=\"\">Password</FormLabel>\n              <FormControl>\n                <Input placeholder=\"password123\" type=\"password\" {...field} />\n              </FormControl>\n              <FormMessage />\n            </FormItem>\n          )}\n        />\n\n        <PasswordStrengthBar password={pass} />\n\n        <div className=\"\">\n          <SubmitButton\n            className=\"w-full my-4 dark:bg-white dark:hover:bg-primary dark:text-black dark:hover:text-white\"\n            isLoading={isLoading}\n            text=\"Sign up\"\n          />\n        </div>\n      </form>\n    </Form>\n  );\n}\n```\n\n```js\n<Input placeholder=\"password123\" onChangeCapture={e => setPass(e.currentTarget.value)} type=\"password\" {...field} />\n```","metadata":{"transformedAt":"2026-08-18T18:33:48.867Z","totalAnswersIncluded":0,"totalCodeBlocksIncluded":3,"totalLines":200,"estimatedTokens":1427}}39{"id":"stack-78551144","source":"stackoverflow","questionId":78551144,"title":"Shadcn/ui Tooltip around Button causes form validation","tags":["reactjs","react-hook-form","zod","shadcnui"],"text":"Title: Shadcn/ui Tooltip around Button causes form validation\nTags: reactjs, react-hook-form, zod, shadcnui\nSource: Stack Overflow\n\nQuestion:\nI'm using the Form component from Shadcn/ui to create a form which also uses **react-hook-form** and **zod**. In this form I have a button called `Button 1` which has a Shadcn/ui Tooltip. The idea behind this is that the user clicks Button 1, and the string \"Button 1\" is stored into the form. Here's the code:\n\n```\nexport default function JobForm() {\n const formSchema = z.object({\n jobName: z.string().min(1).max(50),\n button: z.string().optional(),\n });\n\n const form = useForm>({\n resolver: zodResolver(formSchema),\n defaultValues: {\n jobName: \"\",\n button: \"\",\n },\n });\n\n function onSubmit(values: z.infer) {\n console.log(values);\n }\n \n return (\n \n \n \n (\n \n Job Name\n \n \n \n \n \n )}\n />\n (\n \n Button\n \n \n \n \n form.setValue('button', \"Button 1\")}\n >\n Button 1\n \n \n \n \"This is Button 1\"\n\n \n \n \n \n \n \n )}\n />\n Submit\n \n \n \n );\n}\n```\n\nThe issue is that clicking `Button 1` triggers a validation on the job name field. I only want the submit button to trigger validation. I think it's the Tooltip causing the issue, since removing the Tooltip around `Button 1` fixes the issue. How can I have a Tooltip component around `Button 1` without causing validation on click?\n\n========================================\n\nCode:\n```js\nexport default function JobForm() {\n  const formSchema = z.object({\n    jobName: z.string().min(1).max(50),\n    button: z.string().optional(),\n  });\n\n  const form = useForm<z.infer<typeof formSchema>>({\n    resolver: zodResolver(formSchema),\n    defaultValues: {\n      jobName: \"\",\n      button: \"\",\n    },\n  });\n\n  function onSubmit(values: z.infer<typeof formSchema>) {\n    console.log(values);\n  }\n  \n  return (\n    <div>\n      <Form {...form}>\n        <form onSubmit={form.handleSubmit(onSubmit)} className=\"space-y-8\">\n          <FormField\n            control={form.control}\n            name=\"jobName\"\n            render={({ field }) => (\n              <FormItem>\n                <FormLabel>Job Name</FormLabel>\n                <FormControl>\n                  <Input placeholder=\"Input job name\" {...field} />\n                </FormControl>\n                <FormMessage />\n              </FormItem>\n            )}\n          />\n          <Controller\n            name=\"button\"\n            control={form.control}\n            render={({ field }) => (\n              <FormItem>\n                <FormLabel>Button</FormLabel>\n                <FormControl>\n                  <TooltipProvider>\n                    <Tooltip>\n                      <TooltipTrigger>\n                        <Button\n                          type=\"button\"\n                          className=\"mr-2\"\n                          onClick={() => form.setValue('button', \"Button 1\")}\n                        >\n                          Button 1\n                        </Button>\n                      </TooltipTrigger>\n                      <TooltipContent>\n                        <p>\"This is Button 1\"</p>\n                      </TooltipContent>\n                    </Tooltip>\n                  </TooltipProvider>\n                </FormControl>\n                <FormMessage />\n              </FormItem>\n            )}\n          />\n          <Button type=\"submit\">Submit</Button>\n        </form>\n      </Form>\n    </div>\n  );\n}\n```\n\n```text\nButton 1\n```\n\n```text\nButton 1\n```\n\n```text\nButton 1\n```\n\n```text\nButton 1\n```\n\n```js\n<TooltipTrigger asChild> {/* Add asChild here */}\n  <Button\n    type=\"button\"\n    className=\"mr-2\"\n    onClick={() => handleButtonClick('Button 1')}\n  >\n    Button 1\n  </Button>\n</TooltipTrigger>\n```\n\n```text\nasChild\n```\n\n```text\nToolTipTrigger\n```\n\n```text\nbutton\n```","metadata":{"transformedAt":"2026-08-18T18:33:48.867Z","totalAnswersIncluded":0,"totalCodeBlocksIncluded":9,"totalLines":187,"estimatedTokens":931}}40{"id":"stack-74790564","source":"stackoverflow","questionId":74790564,"title":"Validate field in discriminated union based on other field in zod","tags":["typescript","zod"],"text":"Title: Validate field in discriminated union based on other field in zod\nTags: typescript, zod\nSource: Stack Overflow\n\nQuestion:\nI have the following discriminated union:\n\n```\nenum Option {\n FULL = 'FULL',\n TIME_PERIOD = 'TIME_PERIOD',\n MONTH = 'MONTH',\n}\n\nconst schema = z.discriminatedUnion('option', [\n z.object({ option: z.literal(Option.FULL) }),\n z.object({\n option: z.literal(Option.TIME_PERIOD),\n from: z.date(),\n to: z.date(),\n }),\n z.object({ option: z.literal(Option.MONTH), month: z.date() }),\n])\n```\n\nNow I want to refine the second object, to check if the date `from` is before `to`:\n\n```\nconst schema = z.discriminatedUnion('option', [\n z.object({ option: z.literal(Option.FULL) }),\n z.object({\n option: z.literal(Option.TIME_PERIOD),\n from: z.date(),\n to: z.date(),\n }).refine(\n ({ from, to }) => isBefore(from, to),\n {\n message: '\"from\" must be before \"to\"',\n path: ['from'],\n }\n ),\n z.object({ option: z.literal(Option.MONTH), month: z.date() }),\n])\n```\n\nBut this gives me an error, basically saying \"type ZodEffects is not allowed as ZodDiscriminatedUnionOption\".\n\nHow can I achieve the desired behaivior in validation?\n\nHere is a codesanbox of my problem:\nhttps://codesandbox.io/s/zod-refine-in-discriminated-union-5kve15\n\n========================================\n\nCode:\n```js\nenum Option {\n    FULL = 'FULL',\n    TIME_PERIOD = 'TIME_PERIOD',\n    MONTH = 'MONTH',\n}\n\nconst schema = z.discriminatedUnion('option', [\n  z.object({ option: z.literal(Option.FULL) }),\n  z.object({\n    option: z.literal(Option.TIME_PERIOD),\n    from: z.date(),\n    to: z.date(),\n  }),\n  z.object({ option: z.literal(Option.MONTH), month: z.date() }),\n])\n```\n\n```js\nconst schema = z.discriminatedUnion('option', [\n  z.object({ option: z.literal(Option.FULL) }),\n  z.object({\n    option: z.literal(Option.TIME_PERIOD),\n    from: z.date(),\n    to: z.date(),\n  }).refine(\n    ({ from, to }) => isBefore(from, to),\n    {\n        message: '\"from\" must be before \"to\"',\n        path: ['from'],\n    }\n  ),\n  z.object({ option: z.literal(Option.MONTH), month: z.date() }),\n])\n```\n\n```text\nfrom\n```\n\n```text\nto\n```\n\n```js\nconst schema = z.discriminatedUnion('option', [\n  z.object({ option: z.literal(Option.FULL) }),\n  z.object({\n    option: z.literal(Option.TIME_PERIOD),\n    from: z.date(),\n    to: z.date(),\n  }),\n  z.object({ option: z.literal(Option.MONTH), month: z.date() }),\n]).refine(\n  (data) => {\n    if (data.option === Option.TIME_PERIOD) {\n      return isBefore(data.from, data.to)\n    }\n    return true\n  },\n  {\n    message: '\"from\" must be before \"to\"',\n    path: ['from'],\n  }\n)\n```\n\n========================================\n\nComments:\n- What if `discriminatedUnion` is actually part of a parent object and I have a refine that depend on both the parent level and discriminated sub branches properties? TS suggest doesn't show all branches properties … Like in here`if (branchB.discrProp === \"VAL1\" && barnchB.banchBOnlyProp)` \"banchBOnlyProp\" is not part of suggestions.\n- I'm not sure how this exactly looks like with discriminatedUnion being part of a parent object. But maybe you should take a look at superRefine, which gives you more context. Maybe TS has its limits here, but the values are still there. Post your problem as a separate thread with a good example and you'll surely get better help.\n- Thank you @sebKas, here is the link to my issue","metadata":{"transformedAt":"2026-08-18T18:33:48.867Z","totalAnswersIncluded":0,"totalCodeBlocksIncluded":5,"totalLines":128,"estimatedTokens":840}}41{"id":"stack-73792237","source":"stackoverflow","questionId":73792237,"title":"How get values inside min(), max() in zod?","tags":["reactjs","typescript","zod"],"text":"Title: How get values inside min(), max() in zod?\nTags: reactjs, typescript, zod\nSource: Stack Overflow\n\nQuestion:\nI have the following schema.\n\n```\nconst schema = z.object({\n name: z.string().min(1)\n})\n```\n\nIs there any way in zod to get the value stored in min?\n\n```\nconst minValue = schema.shape...? // should be 1\n```\n\n========================================\n\nTop Answer:\nThis is a way that works for me:\n\n```\nconst stringSchema =\n commentSchema.isOptional() || commentSchema.isNullable()\n ? commentSchema._def.innerType\n : commentSchema;\n\nconst maxLength = stringSchema instanceof z.ZodString\n ? stringSchema._def.checks?.find((check) => check.kind === \"min\")?.value\n```\n\n**Very important**: When the zod schema is optional or nullable, you need to first refer the `._def.innerType`, before you can access the checks.\n\n========================================\n\nCode:\n```text\nconst schema = z.object({\n name: z.string().min(1)\n})\n```\n\n```text\nconst minValue = schema.shape...? // should be 1\n```\n\n```text\nconst minValue = schema.shape.name._def.checks[0].value;\n```\n\n```text\nconst minValue = schema.shape.name._def.checks.find(({ kind }) => kind === \"min\").value;\n```\n\n```js\nconst nameMinLength = 1;\n\nconst schema = z.object({\n name: z.string().min(nameMinLength)\n});\n\n// now you already have it\nconsole.log(nameMinLength);\n```\n\n```text\n_def\n```\n\n```text\n//@ts-ignore\n```\n\n```text\nfind\n```\n\n```text\nundefined\n```\n\n```text\nconst stringSchema =\n  commentSchema.isOptional() || commentSchema.isNullable()\n    ? commentSchema._def.innerType\n    : commentSchema;\n\nconst maxLength = stringSchema instanceof z.ZodString\n  ? stringSchema._def.checks?.find((check) => check.kind === \"min\")?.value\n```\n\n```text\n._def.innerType\n```\n\n```text\nimport * as z from \"zod/v4\";\n\nexport function getMinDate<T extends z.ZodObject<any>>(\n  validationSchema: T,\n  fieldName: keyof z.infer<T>\n) {\n  const shape: z.ZodType = validationSchema.shape[fieldName];\n\n  const min = shape.def.checks?.find(\n    (check) => check._zod.def.check === \"greater_than\"\n  );\n\n  if (min && \"value\" in min._zod.def) {\n    return min._zod.def.value;\n  }\n\n  return null;\n}\n\nexport function getMaxDate<T extends z.ZodObject<any>>(\n  validationSchema: T,\n  fieldName: keyof z.infer<T>\n) {\n  const shape: z.ZodType = validationSchema.shape[fieldName];\n\n  const max = shape.def.checks?.find(\n    (check) => check._zod.def.check === \"less_than\"\n  );\n\n  if (max && \"value\" in max._zod.def) {\n    return max._zod.def.value;\n  }\n\n  return null;\n}\n```","metadata":{"transformedAt":"2026-08-18T18:33:48.867Z","totalAnswersIncluded":1,"totalCodeBlocksIncluded":12,"totalLines":135,"estimatedTokens":626}}42{"id":"stack-74864751","source":"stackoverflow","questionId":74864751,"title":"Cannot read req.body in Next.js 13 middeware","tags":["javascript","next.js","zod","next.js13"],"text":"Title: Cannot read req.body in Next.js 13 middeware\nTags: javascript, next.js, zod, next.js13\nSource: Stack Overflow\n\nQuestion:\nIn the code below I want to validate the request body with a schema from zod, currently, it will fail and catch. This is because `req.body` is returning a `ReadableStream` and not the object that it expects to parse.\n\n```\nexport default async function middleware(req: NextRequest, res: NextResponse) {\n const { pathname } = req.nextUrl;\n if (pathname.startsWith('/api/user/create')) {\n try {\n createUserSchema.parse({\n body: req.body,\n params: req.nextUrl.searchParams,\n });\n return NextResponse.next();\n } catch (error: any) {\n console.log(req.body);\n return NextResponse.json(\n { success: false, message: error },\n { status: 422, headers: { 'content-type': 'application/json' } }\n );\n }\n }\n\n return NextResponse.next();\n}\n```\n\nthis below is the output of the `console.log(req.body);`\n\n```\n ReadableStream {\n _state: 'readable',\n _reader: undefined,\n _storedError: undefined,\n _disturbed: false,\n _readableStreamController: ReadableStreamDefaultController {\n _controlledReadableStream: [Circular *1],\n _queue: S {\n _cursor: 0,\n _size: 0,\n _front: { _elements: [], _next: undefined },\n _back: { _elements: [], _next: undefined }\n},\n _queueTotalSize: 0,\n _started: false,\n _closeRequested: false,\n _pullAgain: false,\n _pulling: false,\n _strategySizeAlgorithm: [Function],\n _strategyHWM: 1,\n _pullAlgorithm: [Function],\n _cancelAlgorithm: [Function]\n}\n}\n```\n\nI did some research and found that I need to run some kind of conversion method on this ReadableStream. The problem is that most of these include the Buffer module which cannot be run on the Edge and therefore cannot work in the `middleware.ts`. Is there perhaps a polyfill that I can use?\n\n`\"next\": \"^13.0.7\"`\n`Node v16.17.0`\n\n========================================\n\nTop Answer:\nYou can use\n\n```\nconst body = await req.json()\n```\n\n========================================\n\nCode:\n```text\nexport default async function middleware(req: NextRequest, res: NextResponse) {\n  const { pathname } = req.nextUrl;\n  if (pathname.startsWith('/api/user/create')) {\n    try {\n      createUserSchema.parse({\n        body: req.body,\n        params: req.nextUrl.searchParams,\n      });\n      return NextResponse.next();\n    } catch (error: any) {\n      console.log(req.body);\n      return NextResponse.json(\n        { success: false, message: error },\n        { status: 422, headers: { 'content-type': 'application/json' } }\n      );\n    }\n  }\n\n  return NextResponse.next();\n}\n```\n\n```text\n<ref *1> ReadableStream {\n  _state: 'readable',\n  _reader: undefined,\n  _storedError: undefined,\n  _disturbed: false,\n  _readableStreamController: ReadableStreamDefaultController {\n  _controlledReadableStream: [Circular *1],\n  _queue: S {\n  _cursor: 0,\n  _size: 0,\n  _front: { _elements: [], _next: undefined },\n  _back: { _elements: [], _next: undefined }\n},\n  _queueTotalSize: 0,\n  _started: false,\n  _closeRequested: false,\n  _pullAgain: false,\n  _pulling: false,\n  _strategySizeAlgorithm: [Function],\n  _strategyHWM: 1,\n  _pullAlgorithm: [Function],\n  _cancelAlgorithm: [Function]\n}\n}\n```\n\n```text\nreq.body\n```\n\n```text\nReadableStream<Uint8Array>\n```\n\n```text\nconsole.log(req.body);\n```\n\n```text\nmiddleware.ts\n```\n\n```text\n\"next\": \"^13.0.7\"\n```\n\n```text\nNode v16.17.0\n```\n\n```text\nconst body = await req.json()\n```\n\n========================================\n\nComments:\n- But is there a way to implement what I am trying to do (validate a post request body in a middleware before hitting endpoint)? Can I add custom express middleware to an api route or am I limited to the Next.js middleware.ts?\n- I have moved this logic to the individual api endpoint as per @emeraldsanto's response and the Next.js middleware documentation that states the following: `To respect the differences in client-side and server-side navigation, and to help ensure that developers do not build insecure Middleware, we are removing the ability to send response bodies in Middleware. This ensures that Middleware is only used to rewrite, redirect, or modify the incoming request (e.g. setting cookies).`\n- If you send empty body from postman you're going to encounter with `Unexpected end of JSON input` error","metadata":{"transformedAt":"2026-08-18T18:33:48.867Z","totalAnswersIncluded":1,"totalCodeBlocksIncluded":9,"totalLines":160,"estimatedTokens":1063}}43{"id":"stack-73827046","source":"stackoverflow","questionId":73827046,"title":"Array of self in Zod schema","tags":["node.js","typescript","zod"],"text":"Title: Array of self in Zod schema\nTags: node.js, typescript, zod\nSource: Stack Overflow\n\nQuestion:\nI'd like to achieve the following:\n\n```\nexport const MediaResponseSchema = z.object({\n mediaId: z.number(),\n childMedias: z.array(z.object(MediaResponseSchema)),\n});\n```\n\nI.e. the `childMedia` should be parsed as an array of the schema I'm declaring.\n\n========================================\n\nCode:\n```text\nexport const MediaResponseSchema = z.object({\n    mediaId: z.number(),\n    childMedias: z.array(z.object(MediaResponseSchema)),\n});\n```\n\n```text\nchildMedia\n```\n\n```text\nimport { z } from \"zod\";\n\n// Zod won't be able to infer the type because it is recursive.\n// if you want to infer as much as possible you could consider using a\n// base schema with the non-recursive fields and then a schema just for\n// the recursive parts of your schema and use `z.union` to join then together.\ninterface IMediaResponse {\n  mediaId: number;\n  childMedias: IMediaResponse[];\n}\n\nconst MediaResponseSchema: z.ZodType<IMediaResponse> = z.lazy(() =>\n  z.object({\n    mediaId: z.number(),\n    childMedias: z.array(MediaResponseSchema)\n  })\n);\n```\n\n```text\nz.lazy\n```\n\n```text\nchildMedia\n```\n\n```text\nchildMedias\n```\n\n========================================\n\nComments:\n- zod.dev/?id=recursive-types\n- What's the difference between that and copy-pasting the whole zod object? In my real example there's 96 lines of code for the original zod object, so not so neat to copy paste everything again.\n- It might be worth asking/answering in a different question if you are concerned about being forced to write out the full interface definition for your type because you can't rely on `z.infer`. That is probably a different issue than just looking for recursion.\n- Thanks for the thorough answer. A bummer though that Zod/TS can't infer, as my schema contains like hundred rows, and is 5 levels deep, so it's quite cumbersome to duplicate the schema code into interfaces.","metadata":{"transformedAt":"2026-08-18T18:33:48.867Z","totalAnswersIncluded":0,"totalCodeBlocksIncluded":6,"totalLines":69,"estimatedTokens":489}}44{"id":"stack-75945904","source":"stackoverflow","questionId":75945904,"title":"zod TypeError: Cannot read properties of undefined (reading '_parse')","tags":["javascript","typescript","zod"],"text":"Title: zod TypeError: Cannot read properties of undefined (reading '_parse')\nTags: javascript, typescript, zod\nSource: Stack Overflow\n\nQuestion:\nI have a Vite library using Zod. I want to parse configurations and my folder structure is similiar to the configuration object structure. `index.ts` files always export all files in their own directory and everything from their subdirectories e.g. `export * from './subDir';` so the root file exports \"the whole lib\".\n\nThe following setup shows a single configuration branch\n\nSample code on Stackblitz\n\n```\n.\n├── src\n│ ├── api\n│ │ ├── dataSources\n| | | ├── dataSource\n| | | | ├── following\n| | | | | ├── computed\n| | | | | | ├── followingComputedDataSourceConfigurationSchema.ts ( extends dataSourceConfigurationSchema )\n| │ │ | | | └── index.ts\n| | | | | ├── entity\n| | | | | | ├── followingEntityDataSourceConfigurationSchema.ts ( extends leadingDataSourceConfigurationSchema )\n| │ │ | | | └── index.ts\n| │ │ | | └── index.ts\n| | | | ├── leading\n| | | | | ├── leadingDataSourceConfigurationSchema.ts ( extends dataSourceConfigurationSchema )\n| │ │ | | └── index.ts\n| | | | ├── dataSourceConfigurationSchema.ts ( base schema )\n│ │ | | └── index.ts\n| | | ├── dataSourcesConfigurationSchema.ts ( expects leading and array of followings )\n│ │ | └── index.ts\n| | ├── apiConfigurationSchema.ts ( expects dataSources )\n│ │ └── index.ts\n│ └── index.ts \n└── test\n └── basic.test.ts\n```\n\nThe problem is that I think I'm running into circular dependency imports. I checked the schema with a test using Vitest\n\n```\nit('fails.', () => {\n expect(() => apiConfigurationSchema.parse({})).not.toThrow();\n});\n```\n\nBy doing so I get the following error\n\nTypeError: Cannot read properties of undefined (reading '_parse')\n\nI don't want to merge the schemas into a single big file because subdirectories might also contain custom validation functions for this specific section.\n\nDo you have any ideas how to fix this setup?\n\n========================================\n\nCode:\n```text\n.\n├── src\n│   ├── api\n│   │   ├── dataSources\n|   |   |   ├── dataSource\n|   |   |   |   ├── following\n|   |   |   |   |   ├── computed\n|   |   |   |   |   |   ├── followingComputedDataSourceConfigurationSchema.ts ( extends dataSourceConfigurationSchema )\n|   │   │   |   |   |   └── index.ts\n|   |   |   |   |   ├── entity\n|   |   |   |   |   |   ├── followingEntityDataSourceConfigurationSchema.ts ( extends leadingDataSourceConfigurationSchema )\n|   │   │   |   |   |   └── index.ts\n|   │   │   |   |   └── index.ts\n|   |   |   |   ├── leading\n|   |   |   |   |   ├── leadingDataSourceConfigurationSchema.ts ( extends dataSourceConfigurationSchema )\n|   │   │   |   |   └── index.ts\n|   |   |   |   ├── dataSourceConfigurationSchema.ts ( base schema )\n│   │   |   |   └── index.ts\n|   |   |   ├── dataSourcesConfigurationSchema.ts ( expects leading and array of followings )\n│   │   |   └── index.ts\n|   |   ├── apiConfigurationSchema.ts ( expects dataSources )\n│   │   └── index.ts\n│   └── index.ts \n└── test\n    └── basic.test.ts\n```\n\n```text\nit('fails.', () => {\n  expect(() => apiConfigurationSchema.parse({})).not.toThrow();\n});\n```\n\n```text\nindex.ts\n```\n\n```text\nexport * from './subDir';\n```\n\n```text\n// index.ts\nexport { apiConfigurationSchema } from './apiConfigurationSchema';\nexport * from './dataSources';\n```\n\n```text\n// apiConfigurationSchema.ts\nimport { dataSourcesConfigurationSchema } from '.';\nexport const used = __use(dataSourcesConfigurationSchema )\n```\n\n```text\n// index.ts\nexport * from './dataSources';\nexport { apiConfigurationSchema } from './apiConfigurationSchema';\n```\n\n```text\n// a.ts\nimport { apiConfigurationSchema } from './src/api/apiConfigurationSchema';\napiConfigurationSchema.parse({});\n```\n\n```text\nindex.ts\n```\n\n```text\n*\n```\n\n```text\ntsx\n```\n\n```text\ntsx watch a\n```\n\n========================================\n\nComments:\n- Thanks a lot for the research details. With this I was able to fix the whole config :)","metadata":{"transformedAt":"2026-08-18T18:33:48.867Z","totalAnswersIncluded":0,"totalCodeBlocksIncluded":12,"totalLines":144,"estimatedTokens":990}}45{"id":"stack-75217817","source":"stackoverflow","questionId":75217817,"title":"zod enum and object as const","tags":["typescript","validation","object","types","zod"],"text":"Title: zod enum and object as const\nTags: typescript, validation, object, types, zod\nSource: Stack Overflow\n\nQuestion:\nI have the following object that is autogenerated\n\n```\nexport const ReportDimensions = {\n CHANNELS: 'CHANNELS',\n DAY: 'DAY',\n DOW: 'DOW',\n MONTH: 'MONTH',\n WEEK: 'WEEK'\n} as const;\n```\n\nI would like to use zod, and allow only value that are in this object, so like\n\n`[\"MONTH\",\"WEEK\",\"DOW\", \"DAY\", \"CHANNELS\"]`\n\nI tried to do\n\n```\nz.enum(Object.keys(ReportDimensions))\n```\n\nbut I get\n\nNo overload matches this call.\nOverload 1 of 2, '(values: readonly [string, ...string[]], params?: RawCreateParams): ZodEnum', gave the following error.\nArgument of type 'string[]' is not assignable to parameter of type 'readonly [string, ...string[]]'.\nSource provides no match for required element at position 0 in target.\nOverload 2 of 2, '(values: [string, ...string[]], params?: RawCreateParams): ZodEnum', gave the following error.\nArgument of type 'string[]' is not assignable to parameter of type '[string, ...string[]]'.\nSource provides no match for required element at position 0 in target.ts(2769)\n\nHow can I properly do this ?\n\n========================================\n\nTop Answer:\nI appreciate this already has an accepted answer, although since that doesn't quite match the OP requirement I can add there is another approach that seems to work for me, using a type-guard return on a call to `refine()`\n\nI have something very similar, like this:\n\n```\nconst EventCodes = {\n FirstEvent: \"FirstEvent\",\n SecondEvent: \"SecondEvent\",\n} as const;\n```\n\nI add an extra type which I can use to mean \"all of the keys of EventCodes\":\n\n```\ntype EventCode = (typeof EventCodes)[keyof typeof EventCodes];\n```\n\nIn the schema that requires an `EventCode` value for a given property, I define a string, and then call `refine()` with a type guard:\n\n```\nconst EventSchema = z.object({\n // here's the magic - the property is a string,\n // but with `refine()` and a type guard we get what we want:\n code: z.string().refine((code): code is EventCode => {\n return Object.values(EventCodes).includes(code as EventCode);\n }),\n message: z.string()\n})\n```\n\nThis works fine, the validation is correct and also if you call `const result = EventSchema.safeParse({ /*...*/ })` the value in `result.data` (when successful!) will give you correct typing.\n\nYou can even infer a type from the schema, and the definition of `code` will respect the type guard from the call to `refine()`:\n\n```\nexport type EventSchemaType = z.infer;\n\nconst goodEvent: EventSchemaType = {\n code: \"FirstEvent\", // this is fine\n message: \"some message\",\n};\n\nconst badEvent: EventSchemaType = {\n code: \"NonExistentEvent\", // this will give a TS error\n message: \"some message\",\n};\n```\n\n========================================\n\nCode:\n```text\nexport const ReportDimensions = {\n  CHANNELS: 'CHANNELS',\n  DAY: 'DAY',\n  DOW: 'DOW',\n  MONTH: 'MONTH',\n  WEEK: 'WEEK'\n} as const;\n```\n\n```text\nz.enum(Object.keys(ReportDimensions))\n```\n\n```text\n[\"MONTH\",\"WEEK\",\"DOW\", \"DAY\", \"CHANNELS\"]\n```\n\n```text\nz.nativeEnum(ReportDimensions)\n```\n\n```text\nconst ReportDimensions = { ... } as const\n```\n\n```text\nconst ReportDimensions = [ 'CHANNELS', 'DAY', 'DOW', 'MONTH', 'WEEK' ] as const;\n```\n\n```ts\nconst EventCodes = {\n  FirstEvent: \"FirstEvent\",\n  SecondEvent: \"SecondEvent\",\n} as const;\n```\n\n```ts\ntype EventCode = (typeof EventCodes)[keyof typeof EventCodes];\n```\n\n```ts\nconst EventSchema = z.object({\n  // here's the magic - the property is a string,\n  // but with `refine()` and a type guard we get what we want:\n  code: z.string().refine((code): code is EventCode => {\n    return Object.values(EventCodes).includes(code as EventCode);\n  }),\n  message: z.string()\n})\n```\n\n```ts\nexport type EventSchemaType = z.infer<typeof EventSchema>;\n\nconst goodEvent: EventSchemaType = {\n  code: \"FirstEvent\", // this is fine\n  message: \"some message\",\n};\n\nconst badEvent: EventSchemaType = {\n  code: \"NonExistentEvent\", // this will give a TS error\n  message: \"some message\",\n};\n```\n\n```text\nrefine()\n```\n\n```text\nEventCode\n```\n\n```text\nrefine()\n```\n\n```text\nconst result = EventSchema.safeParse({ /*...*/ })\n```\n\n```text\nresult.data\n```\n\n```text\ncode\n```\n\n```text\nrefine()\n```","metadata":{"transformedAt":"2026-08-18T18:33:48.868Z","totalAnswersIncluded":1,"totalCodeBlocksIncluded":17,"totalLines":186,"estimatedTokens":1053}}46{"id":"stack-75886482","source":"stackoverflow","questionId":75886482,"title":"Check Zod types are equivalent to a TypeScript interface?","tags":["typescript","zod"],"text":"Title: Check Zod types are equivalent to a TypeScript interface?\nTags: typescript, zod\nSource: Stack Overflow\n\nQuestion:\nIve been asserting that the results of an API call have this shape in TypeScript:\n\n```\ninterface Res {\n films: string;\n people: string;\n}\n\nconst res: Res = await fetch(\"https://swapi.dev/api/\")\n .then((res) => {\n return res.json();\n })\n .then(({ films, people }) => {\n return {\n films,\n people,\n };\n });\n```\n\nLater I added runtime type checking with Zod\n\n```\nconst resSchema = z.object({\n films: z.string(),\n people: z.string(),\n});\n\nresSchema.parse(res);\n```\n\nThis works but it means that I have 2 different type definitions to maintain. Is there a way of checking in TypeScript that the type of `resSchema` is equal to `Res`?\n\nI know that zod can infer:\n\n```\ntype ResType = z.infer\n\n const res: ResType = await fetch(\"https://swapi.dev/api/\")\n .then((res) => {\n return res.json();\n })\n .then(({ films, people }) => {\n return {\n films,\n people,\n };\n });\n```\n\nHowever I dont want to use this as I cant at a glance as easily see the fields on `ResType` compared to `Res` which is very clear.\n\n========================================\n\nTop Answer:\nAlthough the answer from @Souperman works, it does not account for `null`, `undefined`, or optional properties (`?`).\n\nSo I started looking for a solution that would...\n\n**SOLUTION 1:**\n\nThis will account for `null`, `undefined`, or optional properties (`?`).\n\nIt uses the \"tozod\" package. See here for github and npm.\n\nYou can use it like this:\n\n```\nimport { z } from \"zod\";\nimport { toZod } from \"tozod\";\n\ninterface Res {\n films?: string; // Note that \"films\" is now optional\n people: string;\n}\n\nconst schema: toZod = z.object({\n films: z.string().optional(), // removing .optional() will throw an error\n people: z.string(),\n});\n```\n\nI like this solution, but I recently discovered it doesn't handle union well.\n\nWhich is when I found solution 2...\n\n**SOLUTION 2:**\n\nThis is an alternate option, but just like the answer from @Souperman, it does NOT account for `null`, `undefined`, or optional properties (`?`).\n\nI found this solution in this zod issue thread. TS 4.9+ is required.\n\nUsing the new TS `satisfies` keyword with `z.ZodType` we can check that a Zod Type matches the TypeScript interface. Errors will throw if they do not match.\n\nFor example:\n\n```\ntype User = {\n id: number\n name: string\n age: number\n}\n\nconst UserSchema = z.object({\n id: z.number(),\n name: z.string(),\n age: z.number()\n}) satisfies z.ZodType\n```\n\nThis is a cool solution, but it's not good for me since it doesn't account for `null`, `undefined`, and optional properties.\n\n**SOLUTION 3:**\n\nI am currently looking into superstructjs instead of zod because someone on zod thread suggested it. Will report back with more later!\n\n========================================\n\nCode:\n```text\ninterface Res {\n  films: string;\n  people: string;\n}\n\nconst res: Res = await fetch(\"https://swapi.dev/api/\")\n  .then((res) => {\n    return res.json();\n  })\n  .then(({ films, people }) => {\n    return {\n      films,\n      people,\n    };\n  });\n```\n\n```text\nconst resSchema = z.object({\n  films: z.string(),\n  people: z.string(),\n});\n\nresSchema.parse(res);\n```\n\n```text\ntype ResType = z.infer<typeof resSchema>\n\n    const res: ResType = await fetch(\"https://swapi.dev/api/\")\n      .then((res) => {\n        return res.json();\n      })\n      .then(({ films, people }) => {\n        return {\n          films,\n          people,\n        };\n      });\n```\n\n```text\nresSchema\n```\n\n```text\nRes\n```\n\n```text\nResType\n```\n\n```text\nRes\n```\n\n```js\nimport { z } from \"zod\";\n\ninterface Res {\n  films: string;\n  people: string;\n}\n\nconst schema: z.ZodType<Res> = z.object({\n  films: z.string(),\n  people: z.string(),\n});\n```\n\n```text\nRes\n```\n\n```text\nschema\n```\n\n```text\nRes\n```\n\n```text\nschema\n```\n\n```text\nz.object\n```\n\n```text\nZodType\n```\n\n```text\nschema.parse\n```\n\n```text\nRes\n```\n\n```text\nparse\n```\n\n```typescript\nimport { z } from \"zod\";\nimport { toZod } from \"tozod\";\n\ninterface Res {\n  films?: string; // Note that \"films\" is now optional\n  people: string;\n}\n\nconst schema: toZod<Res> = z.object({\n  films: z.string().optional(), // removing .optional() will throw an error\n  people: z.string(),\n});\n```\n\n```typescript\ntype User = {\n    id: number\n    name: string\n    age: number\n}\n\nconst UserSchema = z.object({\n    id: z.number(),\n    name: z.string(),\n    age: z.number()\n}) satisfies z.ZodType<User>\n```\n\n```text\nnull\n```\n\n```text\nundefined\n```\n\n```text\n?\n```\n\n```text\nnull\n```\n\n```text\nundefined\n```\n\n```text\n?\n```\n\n```text\nnull\n```\n\n```text\nundefined\n```\n\n```text\n?\n```\n\n```text\nsatisfies\n```\n\n```text\nz.ZodType\n```\n\n```text\nnull\n```\n\n```text\nundefined\n```\n\n========================================\n\nComments:\n- Very nice. Thank you!\n- Only problem I’ve got with this implementation is that I have to cast this back to ZodObject if I want to extend or omit properties for other schemas.\n- The \"satisfies\" is also useful for my use case - I get zod types auto-generated from openAPI schemas using github.com/astahmer/openapi-zod-client so I don't want to modify them, as I want to re-generate them when the API changes.","metadata":{"transformedAt":"2026-08-18T18:33:48.868Z","totalAnswersIncluded":1,"totalCodeBlocksIncluded":32,"totalLines":319,"estimatedTokens":1286}}47{"id":"stack-74809560","source":"stackoverflow","questionId":74809560,"title":"How to write a tuple with spread type in Zod","tags":["typescript","zod"],"text":"Title: How to write a tuple with spread type in Zod\nTags: typescript, zod\nSource: Stack Overflow\n\nQuestion:\nIn TypeScript, you would write:\n\n```\ntype A = [\"A\", ...string[]];\n```\n\nHow would you define that type definition using Zod?\n\nPlayground\n\n========================================\n\nCode:\n```js\ntype A = [\"A\", ...string[]];\n```\n\n```js\nconst schema = z.tuple([z.literal('A')]).rest(z.string())\n```\n\n```text\nzod\n```\n\n```text\n.rest\n```\n\n========================================\n\nComments:\n- As the name suggests, this supports adding spread only in the end, i.e. it seems like zod for `type A = [...number[], string]` cannot be written this way","metadata":{"transformedAt":"2026-08-18T18:33:48.868Z","totalAnswersIncluded":0,"totalCodeBlocksIncluded":4,"totalLines":38,"estimatedTokens":162}}48{"id":"stack-75876233","source":"stackoverflow","questionId":75876233,"title":"How to parse Zod to identify if field is required?","tags":["react-hook-form","zod"],"text":"Title: How to parse Zod to identify if field is required?\nTags: react-hook-form, zod\nSource: Stack Overflow\n\nQuestion:\nI am wondering if I could use Zod to determine when a field is required so I can pass this boolean to the input e.g. ``. The main reason I asking is for styling purposes such as displaying `*` when the field is required.\n\n```\nconst Component = () => {\n const schema = z.object({\n name: z.string(),\n address: z.string().optional(),\n });\n\n type FormValues = z.infer;\n\n const {\n register,\n handleSubmit,\n formState: { errors },\n } = useForm({\n defaultValues: {\n name: '',\n address: undefined,\n },\n resolver: zodResolver(schema),\n });\n\n const onSubmit = handleSubmit((data) => console.log(data));\n\n return (\n \n \n {errors?.name && {errors.name.message}\n\n}\n\n \n\n \n \n );\n};\n```\n\n========================================\n\nTop Answer:\nI believe you can call the `.isOptional()` method.\n\n```\n\n```\n\n========================================\n\nCode:\n```text\nconst Component = () => {\n  const schema = z.object({\n    name: z.string(),\n    address: z.string().optional(),\n  });\n\n  type FormValues = z.infer<typeof schema>;\n\n  const {\n    register,\n    handleSubmit,\n    formState: { errors },\n  } = useForm<FormValues>({\n    defaultValues: {\n      name: '',\n      address: undefined,\n    },\n    resolver: zodResolver(schema),\n  });\n\n  const onSubmit = handleSubmit((data) => console.log(data));\n\n  return (\n    <form onSubmit={onSubmit}>\n      <input\n        {...register('name', {\n          required: /* Use Zod to determine this value */,\n        })}\n      />\n      {errors?.name && <p>{errors.name.message}</p>}\n\n      <input {...register('address'{\n          required: /* Use Zod to determine this value */,\n        })}\n      />\n\n      <input type=\"submit\" />\n    </form>\n  );\n};\n```\n\n```text\n<input required={/* Use Zod to determine this value */} />\n```\n\n```text\n*\n```\n\n```text\nconst schema = z.number().optional();\n// ...\n\n<input required={!(schema instanceof z.ZodOptional)} />\n```\n\n```text\n<input required={!(schema.shape.name instanceof z.ZodOptional)} />\n```\n\n```text\ninstanceof\n```\n\n```text\nz.ZodOptional\n```\n\n```text\nz.object\n```\n\n```text\nschema\n```\n\n```text\nshape\n```\n\n```text\n.optional()\n```\n\n```text\nZodOptional\n```\n\n```text\nZodEffect\n```\n\n```text\nZodEffect\n```\n\n```text\n<input required={!schema.shape.name.isOptional()} />\n<input required={!schema.shape.address.isOptional()} />\n```\n\n```text\n.isOptional()\n```\n\n========================================\n\nComments:\n- And if the schema is a zod union? How can I check if it is optional?\n- .shape doesn't exist on your example, or in any schema object i have. (zod v.3.23.x)","metadata":{"transformedAt":"2026-08-18T18:33:48.868Z","totalAnswersIncluded":1,"totalCodeBlocksIncluded":16,"totalLines":169,"estimatedTokens":660}}49{"id":"stack-73459017","source":"stackoverflow","questionId":73459017,"title":"Custom validation of optional keys in zod","tags":["javascript","typescript","zod"],"text":"Title: Custom validation of optional keys in zod\nTags: javascript, typescript, zod\nSource: Stack Overflow\n\nQuestion:\nI'm currently evaluating the use of zod in my application and have a small problem when having to parse an object that can contain optional keys.\nI'm using .passthrough to allow the keys to stay in the object but would like to custom validate the keys or at least make sure that the key names and types are valid.\nThe .catchall only allows to specify a type of all optional keys but I would require to custom validate each optional key.\n\n```\nimport {z} from 'zod';\n\n// mandatory user information\nconst user = z.object({\n id: z.number(),\n name: z.string(),\n});\n\n// additional keys like:\n// string: key in the format /^add_\\d{3}_s$/\n// number: key in the format /^add_\\d{3}_n$/ \n\nadd_001_s: z.string()\nadd_002_s: z.string()\nadd_003_n: z.number()\nadd_004_n: z.number()\n```\n\n========================================\n\nCode:\n```js\nimport {z} from 'zod';\n\n// mandatory user information\nconst user = z.object({\n    id: z.number(),\n    name: z.string(),\n});\n\n// additional keys like:\n// string: key in the format /^add_\\d{3}_s$/\n// number: key in the format /^add_\\d{3}_n$/ \n\nadd_001_s: z.string()\nadd_002_s: z.string()\nadd_003_n: z.number()\nadd_004_n: z.number()\n```\n\n```js\nimport { z } from \"zod\";\n\nconst mandatoryFields = z.object({\n  id: z.number(),\n  name: z.string()\n});\n\nconst stringRegex = /^add_\\d{3}_s$/;\nconst optionalStringFields = z.record(\n  z.string().regex(stringRegex),\n  z.string()\n);\n\nconst numberRegex = /^add_\\d{3}_n$/;\nconst optionalNumberFields = z.record(\n  z.string().regex(numberRegex),\n  z.number()\n);\n```\n\n```js\nconst schema = z.preprocess(\n  (args) => {\n    const unknownRecord = z.record(z.string(), z.unknown()).safeParse(args);\n    if (!unknownRecord.success) {\n      // In the event that what was passed in wasn't an unknown record\n      // this skips the rest of the preprocessing and lets the schema\n      // fail with a better error message.\n      return args;\n    }\n    const entries = Object.entries(unknownRecord.data);\n    // Pulls out just stuff that looks like optional number fields\n    const numbers = Object.fromEntries(\n      entries.filter(\n        ([k, v]): [string, unknown] | null => k.match(numberRegex) && [k, v]\n      )\n    );\n    // pulls out just stuff that looks like optional string fields\n    const strings = Object.fromEntries(\n      entries.filter(\n        ([k, v]): [string, unknown] | null => k.match(stringRegex) && [k, v]\n      )\n    );\n    // The types here are all unknowns but now the pieces of the data\n    // have been grouped in a way that those three core schemas can parse them\n    return {\n      mandatory: args,\n      numbers,\n      strings\n    };\n  },\n  z.object({\n    mandatory: mandatoryFields,\n    numbers: optionalNumberFields,\n    strings: optionalStringFields\n  })\n);\n```\n\n```js\nconst test = schema.parse({\n  id: 11,\n  name: \"steve\",\n  add_101_s: \"cat\",\n  add_123_n: 43,\n  dont_care: \"something\"\n});\n\nconsole.log(test);\n/* Logs:\nmandatory: Object\n  id: 11\n  name: \"steve\"\nnumbers: Object\n  add_123_n: 43\nstrings: Object\n  add_101_s: \"cat\"\n*/\n```\n\n```text\nand\n```\n\n```text\npreprocess\n```\n\n```text\ndont_care\n```\n\n```text\npassthrough\n```\n\n========================================\n\nComments:\n- Could you provide an example of the code you're working with as well as the shape of the data you are trying to validate? I'm not sure I fully understand what you're trying to do.\n- @Souperman I have added an example that might help to better understand. There are mandatory keys and an arbitrary number of optional keys and I would like to validate the names/types of the optional keys.\n- I see, the arbitrary nature of the optionals was what I was not understanding. I was thinking you just wanted `optional` at first.\n- Note to help with search indexing. This problem is common when dealing with form data that uses the array notation. For example if you have a `` with `` and submit data, the `FormData` will look like `{'items[0]': 'x', 'items[1]': 'x'}` if reading the entries as an object or `[['items[0]', 'x'], ['items[1]', 'x']]` if reading as an array. E.g. SvelteKit is an opinionated framework that encourages form submissions to your backend over traditional API endpoints, so you may need to make similar schemas when using that.\n- Thank you for the very interesting solution to my use case. So basically preprocess can be used to „rearrange“ the structure of what will be parsed before actually parsing it. Is this the reason why there is no „custom“ type that I would have expected?","metadata":{"transformedAt":"2026-08-18T18:33:48.868Z","totalAnswersIncluded":0,"totalCodeBlocksIncluded":8,"totalLines":155,"estimatedTokens":1145}}50{"id":"stack-73980097","source":"stackoverflow","questionId":73980097,"title":"ZOD [Error]: Schema with id 'Schema' already declared","tags":["typescript","fastify","zod"],"text":"Title: ZOD [Error]: Schema with id 'Schema' already declared\nTags: typescript, fastify, zod\nSource: Stack Overflow\n\nQuestion:\nI am new to Fastify and Typescript. I am working on adding Zod schemas for validation and I am getting this error:\n\n```\n/app/node_modules/fastify/lib/schemas.js:32\n throw new FST_ERR_SCH_ALREADY_PRESENT(id)\n ^\nFastifyError [Error]: Schema with id 'Schema' already declared!\n at Schemas.add (/app/node_modules/fastify/lib/schemas.js:32:11)\n at SchemaController.add (/app/node_modules/fastify/lib/schema-controller.js:58:30)\n at Object.addSchema (/app/node_modules/fastify/fastify.js:601:29)\n at /app/src/index.ts:23:12\n at Generator.next ()\n at /app/src/index.ts:8:71\n at new Promise ()\n at __awaiter (/app/src/index.ts:4:12)\n at main (/app/src/index.ts:32:12)\n at Object. (/app/src/index.ts:63:1) {\n code: 'FST_ERR_SCH_ALREADY_PRESENT',\n statusCode: 500\n```\n\nFrom Fastify docs:\n\n```\nFST_ERR_SCH_ALREADY_PRESENT\nA schema with the same $id already exists.\n```\n\nI am not sure where eaxctly is this `$id` being set\n\nWhen I just had one schema and was adding it to fastify in `index.ts` it was working:\n\n```\nfor (const schema of userSchemas) {\n server.addSchema(schema);\n}\n```\n\nBut adding another schema, throws the above error:\n\n```\nfor (const schema of [...userSchemas, ...teamSchemas]) {\n server.addSchema(schema);\n}\n```\n\n`package.json` versions\n\n```\n\"fastify\": \"^4.6.0\",\n \"fastify-cors\": \"^6.1.0\",\n \"fastify-zod\": \"^1.2.0\",\n \"zod\": \"3.19.1\",\n \"zod-to-json-schema\": \"^3.18.1\"\n```\n\nuser schema:\n\n```\nimport { z } from 'zod';\nimport { buildJsonSchemas } from 'fastify-zod';\nimport {\n CreateUserRequest,\n UpdateUserRequest,\n UserResponse\n} from '../../services/user/interface';\n\nconst createUserSchema: z.ZodSchema = CreateUserRequest;\n\nconst updateUserSchema: z.ZodSchema = UpdateUserRequest;\n\nconst responseUserSchema: z.ZodSchema = UserResponse;\n\nexport const { schemas: userSchemas, $ref } = buildJsonSchemas({\n createUserSchema,\n updateUserSchema,\n responseUserSchema\n});\n```\n\nteam schema\n\n```\nimport { buildJsonSchemas } from 'fastify-zod';\nimport { z } from 'zod';\nimport {\n CreateTeamRequest,\n TeamResponse,\n UpdateTeamRequest\n} from '../../services/team/interface';\n\nconst createTeamSchema: z.ZodSchema = CreateTeamRequest;\n\nconst updateTeamSchema: z.ZodSchema = UpdateTeamRequest;\n\nconst responseTeamSchema: z.ZodSchema = TeamResponse;\n\nexport const { schemas: teamSchemas, $ref } = buildJsonSchemas({\n createTeamSchema,\n updateTeamSchema,\n responseTeamSchema\n});\n```\n\nLooks like it was an issue last year, but has been resolved since: https://github.com/fastify/fastify/issues/2914\n\nAny idea what I maybe be missing here.\n\nEDIT:\nconsole.log(schema) before addSchema gives:\n\n```\n{\n '$id': 'Schema',\n '$schema': 'http://json-schema.org/draft-07/schema#',\n type: 'object',\n properties: {\n createUserSchema: {\n type: 'object',\n properties: [Object],\n required: [Array],\n additionalProperties: false\n },\n updateUserSchema: {\n type: 'object',\n properties: [Object],\n additionalProperties: false\n },\n responseUserSchema: {\n type: 'object',\n properties: [Object],\n required: [Array],\n additionalProperties: false\n }\n },\n required: [ 'createUserSchema', 'updateUserSchema', 'responseUserSchema' ],\n additionalProperties: false\n}\n{\n '$id': 'Schema',\n '$schema': 'http://json-schema.org/draft-07/schema#',\n type: 'object',\n properties: {\n createTeamSchema: {\n type: 'object',\n properties: [Object],\n required: [Array],\n additionalProperties: false\n },\n updateTeamSchema: {\n type: 'object',\n properties: [Object],\n required: [Array],\n additionalProperties: false\n },\n deleteTeamSchema: {\n type: 'object',\n properties: [Object],\n required: [Array],\n additionalProperties: false\n },\n responseTeamSchema: {\n type: 'object',\n properties: [Object],\n required: [Array],\n additionalProperties: false\n }\n },\n required: [\n 'createTeamSchema',\n 'updateTeamSchema',\n 'deleteTeamSchema',\n 'responseTeamSchema'\n ],\n additionalProperties: false\n}\n```\n\n========================================\n\nCode:\n```text\n/app/node_modules/fastify/lib/schemas.js:32\n    throw new FST_ERR_SCH_ALREADY_PRESENT(id)\n          ^\nFastifyError [Error]: Schema with id 'Schema' already declared!\n    at Schemas.add (/app/node_modules/fastify/lib/schemas.js:32:11)\n    at SchemaController.add (/app/node_modules/fastify/lib/schema-controller.js:58:30)\n    at Object.addSchema (/app/node_modules/fastify/fastify.js:601:29)\n    at /app/src/index.ts:23:12\n    at Generator.next (<anonymous>)\n    at /app/src/index.ts:8:71\n    at new Promise (<anonymous>)\n    at __awaiter (/app/src/index.ts:4:12)\n    at main (/app/src/index.ts:32:12)\n    at Object.<anonymous> (/app/src/index.ts:63:1) {\n  code: 'FST_ERR_SCH_ALREADY_PRESENT',\n  statusCode: 500\n```\n\n```text\nFST_ERR_SCH_ALREADY_PRESENT\nA schema with the same $id already exists.\n```\n\n```text\nfor (const schema of userSchemas) {\n   server.addSchema(schema);\n}\n```\n\n```text\nfor (const schema of [...userSchemas, ...teamSchemas]) {\n   server.addSchema(schema);\n}\n```\n\n```text\n\"fastify\": \"^4.6.0\",\n \"fastify-cors\": \"^6.1.0\",\n \"fastify-zod\": \"^1.2.0\",\n \"zod\": \"3.19.1\",\n \"zod-to-json-schema\": \"^3.18.1\"\n```\n\n```text\nimport { z } from 'zod';\nimport { buildJsonSchemas } from 'fastify-zod';\nimport {\n  CreateUserRequest,\n  UpdateUserRequest,\n  UserResponse\n} from '../../services/user/interface';\n\nconst createUserSchema: z.ZodSchema<CreateUserRequest> = CreateUserRequest;\n\nconst updateUserSchema: z.ZodSchema<UpdateUserRequest> = UpdateUserRequest;\n\nconst responseUserSchema: z.ZodSchema<UserResponse> = UserResponse;\n\nexport const { schemas: userSchemas, $ref } = buildJsonSchemas({\n  createUserSchema,\n  updateUserSchema,\n  responseUserSchema\n});\n```\n\n```text\nimport { buildJsonSchemas } from 'fastify-zod';\nimport { z } from 'zod';\nimport {\n  CreateTeamRequest,\n  TeamResponse,\n  UpdateTeamRequest\n} from '../../services/team/interface';\n\nconst createTeamSchema: z.ZodSchema<CreateTeamRequest> = CreateTeamRequest;\n\nconst updateTeamSchema: z.ZodSchema<UpdateTeamRequest> = UpdateTeamRequest;\n\nconst responseTeamSchema: z.ZodSchema<TeamResponse> = TeamResponse;\n\nexport const { schemas: teamSchemas, $ref } = buildJsonSchemas({\n  createTeamSchema,\n  updateTeamSchema,\n  responseTeamSchema\n});\n```\n\n```text\n{\n  '$id': 'Schema',\n  '$schema': 'http://json-schema.org/draft-07/schema#',\n  type: 'object',\n  properties: {\n    createUserSchema: {\n      type: 'object',\n      properties: [Object],\n      required: [Array],\n      additionalProperties: false\n    },\n    updateUserSchema: {\n      type: 'object',\n      properties: [Object],\n      additionalProperties: false\n    },\n    responseUserSchema: {\n      type: 'object',\n      properties: [Object],\n      required: [Array],\n      additionalProperties: false\n    }\n  },\n  required: [ 'createUserSchema', 'updateUserSchema', 'responseUserSchema' ],\n  additionalProperties: false\n}\n{\n  '$id': 'Schema',\n  '$schema': 'http://json-schema.org/draft-07/schema#',\n  type: 'object',\n  properties: {\n    createTeamSchema: {\n      type: 'object',\n      properties: [Object],\n      required: [Array],\n      additionalProperties: false\n    },\n    updateTeamSchema: {\n      type: 'object',\n      properties: [Object],\n      required: [Array],\n      additionalProperties: false\n    },\n    deleteTeamSchema: {\n      type: 'object',\n      properties: [Object],\n      required: [Array],\n      additionalProperties: false\n    },\n    responseTeamSchema: {\n      type: 'object',\n      properties: [Object],\n      required: [Array],\n      additionalProperties: false\n    }\n  },\n  required: [\n    'createTeamSchema',\n    'updateTeamSchema',\n    'deleteTeamSchema',\n    'responseTeamSchema'\n  ],\n  additionalProperties: false\n}\n```\n\n```text\n$id\n```\n\n```text\nindex.ts\n```\n\n```text\npackage.json\n```\n\n```text\nimport { buildJsonSchemas } from 'fastify-zod';\n\nconst { schemas, $ref } = buildJsonSchemas(models, { $id: \"MySchema\" });\n```\n\n```text\nfastify-zod\n```\n\n```text\nSchema\n```\n\n========================================\n\nComments:\n- I would add a `console.log(schema)` before running the `addSchema`. What does it show?\n- Hi @ManuelSpigolon sorry for the late reply, I added the console log above.\n- As you can see, both have the `'$id': 'Schema',`. You need to change it\n- Yeah, the question is where do I change it? I am not sure, I think I don't set it explicitly anywhere.\n- I need to check zod, I don't know how it works, but it is definitely setting those ids\n- I have looked into it, but can't find the id setting :/\n- hi do you mind how you add id explicitly in this answer ? thanks\n- Sure, something like this: const { schemas, $ref } = buildJsonSchemas(models, { $id: \"MySchema\" });","metadata":{"transformedAt":"2026-08-18T18:33:48.868Z","totalAnswersIncluded":0,"totalCodeBlocksIncluded":14,"totalLines":378,"estimatedTokens":2161}}51{"id":"stack-76293170","source":"stackoverflow","questionId":76293170,"title":"Property 'shape' does not exist on type in Zod?","tags":["typescript","zod"],"text":"Title: Property 'shape' does not exist on type in Zod?\nTags: typescript, zod\nSource: Stack Overflow\n\nQuestion:\nI am doing this in Zod:\n\n```\nexport const LoadSort: z.ZodType = z.object({\n name: z.string(),\n tilt: z.enum(['+', '-']),\n})\n\nconsole.log(LoadSort.shape)\n```\n\nBut getting an error on `.shape`:\n\nProperty 'shape' does not exist on type 'ZodType'.ts(2339)\n\nActually, my code is more complex and requires me to use non-inferred types. Here is my full code\n\n```\nimport { z } from 'zod'\n\nexport const LOAD_FIND_TEST = [\n 'bond',\n 'base_link_mark',\n 'head_link_mark',\n 'base_mark',\n 'head_mark',\n 'base_text',\n 'miss_bond',\n 'have_bond',\n 'have_text',\n] as const\n\nexport type Load = {\n find?: LoadFind\n read?: LoadRead\n save?: LoadSave\n task?: string\n}\n\nexport type LoadFind = LoadFindLink | Array\n\nexport type LoadFindBind = {\n form: 'bind'\n list: Array\n}\n\nexport type LoadFindLike = {\n base: LoadFindLikeLinkBond\n form: 'like'\n head: LoadFindLikeBond | LoadFindLikeLinkBond\n test: LoadFindTest\n}\n\nexport type LoadFindLikeBond = string | boolean | null | number\n\nexport type LoadFindLikeLinkBond = {\n link: string\n}\n\nexport type LoadFindLink = LoadFindLike | LoadFindRoll | LoadFindBind\n\nexport type LoadFindRoll = {\n form: 'roll'\n list: Array\n}\n\nexport type LoadFindTest = (typeof LOAD_FIND_TEST)[number]\n\nexport type LoadRead = {\n [key: string]: true | LoadReadLink\n}\n\nexport type LoadReadLink = {\n find?: LoadFind\n read: LoadRead\n}\n\nexport type LoadSave = {\n [key: string]: Array | LoadSaveBase\n}\n\nexport type LoadSaveBase = {\n find?: LoadFind\n read?: LoadRead\n save?: LoadSave\n task?: string\n}\n\nexport type LoadSort = {\n name: string\n tilt: '+' | '-'\n}\n\nexport const Load: z.ZodType = z.object({\n find: z.optional(z.lazy(() => LoadFind)),\n read: z.optional(z.lazy(() => LoadRead)),\n save: z.optional(z.lazy(() => LoadSave)),\n task: z.optional(z.string()),\n})\n\nexport const LoadFind: z.ZodType = z.union([\n z.lazy(() => LoadFindLink),\n z.array(z.lazy(() => LoadFindLink)),\n])\n\nexport const LoadRead: z.ZodType = z.record(\n z.union([z.lazy(() => LoadReadLink), z.literal(true)]),\n)\n\nexport const LoadSave: z.ZodType = z.record(\n z.union(\n z.array(z.lazy(() => LoadSaveBase)),\n z.lazy(() => LoadSaveBase),\n ),\n)\n\nexport const LoadFindBind: z.ZodType = z.object({\n form: z.literal('bind'),\n list: z.array(z.lazy(() => LoadFindLink)),\n})\n\nexport const LoadFindRoll: z.ZodType = z.object({\n form: z.literal('roll'),\n list: z.lazy(() => z.array(LoadFindLink)),\n})\n\nexport const LoadFindTest = z.enum([\n 'bond',\n 'base_link_mark',\n 'head_link_mark',\n 'base_mark',\n 'head_mark',\n 'base_text',\n 'miss_bond',\n 'have_bond',\n 'have_text',\n])\n\nexport const LoadFindLike: z.ZodType = z.object({\n base: z.lazy(() => LoadFindLikeLinkBond),\n form: z.literal('like'),\n head: z.union([\n z.lazy(() => LoadFindLikeLinkBond),\n z.lazy(() => LoadFindLikeBond),\n ]),\n test: LoadFindTest,\n})\n\nexport const LoadFindLink: z.ZodType = z.union([\n z.lazy(() => LoadFindLike),\n z.lazy(() => LoadFindRoll),\n z.lazy(() => LoadFindBind),\n])\n\nexport const LoadFindLikeBond: z.ZodType = z.union([\n z.string(),\n z.boolean(),\n z.null(),\n z.number(),\n])\n\nexport const LoadFindLikeLinkBond: z.ZodType =\n z.object({\n link: z.string(),\n })\n\nexport const LoadReadLink: z.ZodType = z.object({\n find: z.optional(LoadFind),\n read: LoadRead,\n})\n\nexport const LoadSaveBase: z.ZodType = z.object({\n find: z.optional(LoadFind),\n read: z.optional(LoadRead),\n save: z.optional(LoadSave),\n task: z.optional(z.string()),\n})\n\nexport const LoadSort: z.ZodType = z.object({\n name: z.string(),\n tilt: z.enum(['+', '-']),\n})\n```\n\nHow do I both specify the `ZodType` and at the same time still get access to all the properties like `.shape` that come on the inferred object?\n\nI am able to sort of get it working with this hack, but it doesn't seem right:\n\n```\nexport const LoadSort: z.ZodType = z.object({\n name: z.string(),\n tilt: z.enum(['+', '-']),\n})\n\nassertZodObject(LoadSort)\n\nfor (const name in LoadSort.shape) {\n const def = LoadSort.shape[name] as z.ZodType\n console.log(def)\n}\n\nexport function assertZodObject>(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n x: any,\n): asserts x is S {\n if (!(x instanceof z.ZodObject)) {\n throw new Error()\n }\n}\n```\n\n========================================\n\nTop Answer:\nI found this to work (slightly different case using `.refine()`, but could be useful for people finding this):\n\nJust remove the extra typing, and export the shape separately like this:\n(`.refine()` changes the type)\n\n```\nexport const mySchema = z.object({ email: z... }).refine(...)\n\n// Access the underlying parent schema with `._def` that refine() gives you\nexport const schemaShape = mySchema.sourceType()._def.shape()\n```\n\n========================================\n\nCode:\n```text\nexport const LoadSort: z.ZodType<LoadSort> = z.object({\n  name: z.string(),\n  tilt: z.enum(['+', '-']),\n})\n\nconsole.log(LoadSort.shape)\n```\n\n```text\nimport { z } from 'zod'\n\nexport const LOAD_FIND_TEST = [\n  'bond',\n  'base_link_mark',\n  'head_link_mark',\n  'base_mark',\n  'head_mark',\n  'base_text',\n  'miss_bond',\n  'have_bond',\n  'have_text',\n] as const\n\nexport type Load = {\n  find?: LoadFind\n  read?: LoadRead\n  save?: LoadSave\n  task?: string\n}\n\nexport type LoadFind = LoadFindLink | Array<LoadFindLink>\n\nexport type LoadFindBind = {\n  form: 'bind'\n  list: Array<LoadFindLink>\n}\n\nexport type LoadFindLike = {\n  base: LoadFindLikeLinkBond\n  form: 'like'\n  head: LoadFindLikeBond | LoadFindLikeLinkBond\n  test: LoadFindTest\n}\n\nexport type LoadFindLikeBond = string | boolean | null | number\n\nexport type LoadFindLikeLinkBond = {\n  link: string\n}\n\nexport type LoadFindLink = LoadFindLike | LoadFindRoll | LoadFindBind\n\nexport type LoadFindRoll = {\n  form: 'roll'\n  list: Array<LoadFindLink>\n}\n\nexport type LoadFindTest = (typeof LOAD_FIND_TEST)[number]\n\nexport type LoadRead = {\n  [key: string]: true | LoadReadLink\n}\n\nexport type LoadReadLink = {\n  find?: LoadFind\n  read: LoadRead\n}\n\nexport type LoadSave = {\n  [key: string]: Array<LoadSaveBase> | LoadSaveBase\n}\n\nexport type LoadSaveBase = {\n  find?: LoadFind\n  read?: LoadRead\n  save?: LoadSave\n  task?: string\n}\n\nexport type LoadSort = {\n  name: string\n  tilt: '+' | '-'\n}\n\nexport const Load: z.ZodType<Load> = z.object({\n  find: z.optional(z.lazy(() => LoadFind)),\n  read: z.optional(z.lazy(() => LoadRead)),\n  save: z.optional(z.lazy(() => LoadSave)),\n  task: z.optional(z.string()),\n})\n\nexport const LoadFind: z.ZodType<LoadFind> = z.union([\n  z.lazy(() => LoadFindLink),\n  z.array(z.lazy(() => LoadFindLink)),\n])\n\nexport const LoadRead: z.ZodType<LoadRead> = z.record(\n  z.union([z.lazy(() => LoadReadLink), z.literal(true)]),\n)\n\nexport const LoadSave: z.ZodType<LoadSave> = z.record(\n  z.union(\n    z.array(z.lazy(() => LoadSaveBase)),\n    z.lazy(() => LoadSaveBase),\n  ),\n)\n\nexport const LoadFindBind: z.ZodType<LoadFindBind> = z.object({\n  form: z.literal('bind'),\n  list: z.array(z.lazy(() => LoadFindLink)),\n})\n\nexport const LoadFindRoll: z.ZodType<LoadFindRoll> = z.object({\n  form: z.literal('roll'),\n  list: z.lazy(() => z.array(LoadFindLink)),\n})\n\nexport const LoadFindTest = z.enum([\n  'bond',\n  'base_link_mark',\n  'head_link_mark',\n  'base_mark',\n  'head_mark',\n  'base_text',\n  'miss_bond',\n  'have_bond',\n  'have_text',\n])\n\nexport const LoadFindLike: z.ZodType<LoadFindLike> = z.object({\n  base: z.lazy(() => LoadFindLikeLinkBond),\n  form: z.literal('like'),\n  head: z.union([\n    z.lazy(() => LoadFindLikeLinkBond),\n    z.lazy(() => LoadFindLikeBond),\n  ]),\n  test: LoadFindTest,\n})\n\nexport const LoadFindLink: z.ZodType<LoadFindLink> = z.union([\n  z.lazy(() => LoadFindLike),\n  z.lazy(() => LoadFindRoll),\n  z.lazy(() => LoadFindBind),\n])\n\nexport const LoadFindLikeBond: z.ZodType<LoadFindLikeBond> = z.union([\n  z.string(),\n  z.boolean(),\n  z.null(),\n  z.number(),\n])\n\nexport const LoadFindLikeLinkBond: z.ZodType<LoadFindLikeLinkBond> =\n  z.object({\n    link: z.string(),\n  })\n\nexport const LoadReadLink: z.ZodType<LoadReadLink> = z.object({\n  find: z.optional(LoadFind),\n  read: LoadRead,\n})\n\nexport const LoadSaveBase: z.ZodType<LoadSaveBase> = z.object({\n  find: z.optional(LoadFind),\n  read: z.optional(LoadRead),\n  save: z.optional(LoadSave),\n  task: z.optional(z.string()),\n})\n\nexport const LoadSort: z.ZodType<LoadSort> = z.object({\n  name: z.string(),\n  tilt: z.enum(['+', '-']),\n})\n```\n\n```text\nexport const LoadSort: z.ZodType<LoadSort> = z.object({\n  name: z.string(),\n  tilt: z.enum(['+', '-']),\n})\n\nassertZodObject(LoadSort)\n\nfor (const name in LoadSort.shape) {\n  const def = LoadSort.shape[name] as z.ZodType\n  console.log(def)\n}\n\nexport function assertZodObject<S extends z.ZodObject<z.ZodRawShape>>(\n  // eslint-disable-next-line @typescript-eslint/no-explicit-any\n  x: any,\n): asserts x is S {\n  if (!(x instanceof z.ZodObject)) {\n    throw new Error()\n  }\n}\n```\n\n```text\n.shape\n```\n\n```text\nZodType\n```\n\n```text\n.shape\n```\n\n```text\nconst LoadSort = z.object({\n  name: z.string(),\n  tilt: z.enum(['+', '-']),\n}) satisfies z.ZodType<LoadSort>\n```\n\n```text\nLoadSort\n```\n\n```text\nz.ZodType<LoadSort>\n```\n\n```text\n.shape\n```\n\n```text\nZodObject\n```\n\n```text\nZodType\n```\n\n```text\n.shape\n```\n\n```text\nsatisfies\n```\n\n```text\nexport const mySchema = z.object({ email: z... }).refine(...)\n\n// Access the underlying parent schema with `._def` that refine() gives you\nexport const schemaShape = mySchema.sourceType()._def.shape()\n```\n\n```text\n.refine()\n```\n\n```text\n.refine()\n```\n\n```text\nshape\n```\n\n```text\nif (schema instanceof ZodObject) {\n```\n\n========================================\n\nComments:\n- That gets me further, but now I have another issue: imgur.com/a/NnsZZ9K any ideas?\n- that is the limitation of typescript (type of key is `string`), I am not test it but maybe try `Object.values` or `Object.entries` will be helped? And about this question (index access), it seems to be very common asked question in stackoverflow.\n- I see that, but it's so strange I need that, why?","metadata":{"transformedAt":"2026-08-18T18:33:48.868Z","totalAnswersIncluded":1,"totalCodeBlocksIncluded":19,"totalLines":509,"estimatedTokens":2484}}52{"id":"stack-76256925","source":"stackoverflow","questionId":76256925,"title":"How to allow passthrough of object fields that are not specified in the schema?","tags":["javascript","express","zod"],"text":"Title: How to allow passthrough of object fields that are not specified in the schema?\nTags: javascript, express, zod\nSource: Stack Overflow\n\nQuestion:\nI am trying to validate just a subset of my request data using `zod`. However, it is filtering out everything that I do not explicitly specify.\n\n```\nconst { z } = require('zod');\n\nconst schema = z.object({\n params: z.object({ dependent_id: z.string() }),\n})\n\nconst req = {\n params: { dependent_id: \"blah\", bar: \"baz\" },\n body: { foo: \"bar\" },\n query: {}\n}\n\nconst test = async () => {\n const { params, body, query } = await schema.parseAsync(req);\n console.log(\"params: \", params)\n console.log(\"body: \", body)\n console.log(\"query: \", query)\n}\n\ntest()\n```\n\nThis is printing out:\n\n```\nparams: { dependent_id: 'blah' } // expect it to print { dependent_id: \"blah\", \"bar\": baz }\nbody: undefined // expect it to print { foo: \"bar\" }\nquery: undefined // expect it to print {},\n```\n\nIs there a way to tell it to ignore everything that is not part of the schema?\n\n========================================\n\nCode:\n```text\nconst { z } = require('zod');\n\nconst schema = z.object({\n  params: z.object({ dependent_id: z.string() }),\n})\n\nconst req = {\n  params: { dependent_id: \"blah\", bar: \"baz\" },\n  body: { foo: \"bar\" },\n  query: {}\n}\n\nconst test = async () => {\n const { params, body, query } = await schema.parseAsync(req);\n  console.log(\"params: \", params)\n  console.log(\"body: \", body)\n  console.log(\"query: \", query)\n}\n\ntest()\n```\n\n```text\nparams:  { dependent_id: 'blah' }         // expect it to print { dependent_id: \"blah\", \"bar\": baz }\nbody:  undefined                          // expect it to print { foo: \"bar\" }\nquery:  undefined                         // expect it to print {},\n```\n\n```text\nzod\n```\n\n```js\nconst test = async () => {\n  const { params, body, query } = await schema.passthrough().parseAsync(req);\n  console.log(\"params: \", params)\n  console.log(\"body: \", body)\n  console.log(\"query: \", query)\n}\n```\n\n```text\n.passthrough\n```\n\n========================================\n\nComments:\n- Please don't tag your titles. See How to Ask.\n- one wonders what you're using zod for if you're not going to type the majority of the response. Seems like you may as well just `const { params, body, query } = req`\n- this doesn't work for nested objects. best I can tell you have to declare `passthrough()` on every nested object.\n- This function helps me remember to use it `function objectPassthrough(arg: T) { return z.object(arg).passthrough(); }`","metadata":{"transformedAt":"2026-08-18T18:33:48.868Z","totalAnswersIncluded":0,"totalCodeBlocksIncluded":5,"totalLines":96,"estimatedTokens":625}}53{"id":"stack-76672351","source":"stackoverflow","questionId":76672351,"title":"Error messages from react-hook-form with zod","tags":["reactjs","typescript","react-hook-form","zod"],"text":"Title: Error messages from react-hook-form with zod\nTags: reactjs, typescript, react-hook-form, zod\nSource: Stack Overflow\n\nQuestion:\nI created a customer registration form, but all my \"messages\" from my \"errors\" are coming as required. Does anyone know what it could be? Something I set up wrong in zod or react-hook-form. Below I will leave the prints of the code.\n\nThis is my generic input component:\n\n```\nimport { DetailedHTMLProps, InputHTMLAttributes } from 'react'\n\ninterface InputProps\n extends DetailedHTMLProps,\n HTMLInputElement\n > {\n label: string\n error?: string\n}\n\nexport const Input = ({ error, label, ...rest }: InputProps) => {\n return (\n \n \n {label}\n \n \n {error && {error}}\n \n )\n}\n```\n\nAnd here is where I created my schema and where I am using this generic input component inside the form:\n\n```\nimport { Input } from '../Input'\nimport { Modal } from '../Modal'\n\nimport { z } from 'zod'\nimport { useForm } from 'react-hook-form'\nimport { zodResolver } from '@hookform/resolvers/zod'\n\ninterface ClientRegistrationModalProps {\n isOpen: boolean\n onClose: () => void\n}\n\nconst createUserFormSchema = z.object({\n name: z\n .string()\n .min(2, 'Password must be at least 2 characters long')\n .transform((name) =>\n name\n .trim()\n .split(' ')\n .map((word) => {\n return word[0].toLocaleUpperCase().concat(word.substring(1))\n })\n .join(' '),\n ),\n email: z\n .string()\n .email('Invalid e-mail format')\n .nonempty('E-mail is required'),\n birthdate: z.string().nonempty('Date of birth is mandatory'),\n cpf: z.string().length(11, 'CPF mus have 11 digits'),\n})\n\ntype CreateUserFormData = z.infer\n\nexport const ClientRegistrationModal = ({\n isOpen,\n onClose,\n}: ClientRegistrationModalProps) => {\n const {\n register,\n handleSubmit,\n formState: { errors, isSubmitting },\n reset,\n } = useForm({\n mode: 'all',\n resolver: zodResolver(createUserFormSchema),\n })\n\n // High-order function\n function createUser(data: CreateUserFormData) {\n console.log(data)\n }\n\n function resetForm() {\n onClose()\n reset()\n }\n\n console.log(errors)\n\n return (\n \n \n \n \n\n \n\n \n\n \n \n \n \n Cadastrar\n \n \n Cancelar\n \n \n \n \n )\n}\n```\n\n**The problem here is**, when I give console.log(errors), **my errors are all as \"Required\"**, that is, they are not showing the error messages that I set inside my schema.\n\nI don't know what could be wrong and would like some help. Maybe it's some typing issue or something I configured wrong. I appreciate any help.\n\nInstead of using that:\n`name: z.string().min(2, 'The name needs at least 2 characters')`\n\nI used this:\n`name: z.string().min(2,{ message: 'The name needs at least 2 characters' })`\n\nBut it didn't work.\n\n========================================\n\nTop Answer:\nI faced the same problem when using `zod` with `react-hook-form`. Even though i added custom message in zod object but still im getting error message as `Required`. after searching through the net i found this article.\n\nIn the article i found out this `errors={errors[\"name\"] && `${(errors[\"name\"] as DeepMap).message}`}`\nand it worked for me\n\n```\n).message}`}\n register={register}\n/>\n```\n\n`DeepMap` is a package from `react-hook-form`\n\nreference:\nhttps://www.react-hook-form.com/ts/#FieldErrors\n\n========================================\n\nCode:\n```text\nimport { DetailedHTMLProps, InputHTMLAttributes } from 'react'\n\ninterface InputProps\n  extends DetailedHTMLProps<\n    InputHTMLAttributes<HTMLInputElement>,\n    HTMLInputElement\n  > {\n  label: string\n  error?: string\n}\n\nexport const Input = ({ error, label, ...rest }: InputProps) => {\n  return (\n    <div className=\"flex flex-col\">\n      <label\n        className=\"mb-2 block text-sm font-bold text-zinc-700\"\n        htmlFor={rest.id}\n      >\n        {label}\n      </label>\n      <input\n        type=\"text\"\n        className={`appearance-none rounded-md border border-zinc-300 px-3 py-2 leading-tight shadow-sm focus:border-zinc-500 focus:outline-none\n        ${error ? 'border-red-500' : 'border-zinc-300'}`}\n        {...rest}\n      />\n      {error && <span className=\"text-xs text-red-500\">{error}</span>}\n    </div>\n  )\n}\n```\n\n```text\nimport { Input } from '../Input'\nimport { Modal } from '../Modal'\n\nimport { z } from 'zod'\nimport { useForm } from 'react-hook-form'\nimport { zodResolver } from '@hookform/resolvers/zod'\n\ninterface ClientRegistrationModalProps {\n  isOpen: boolean\n  onClose: () => void\n}\n\nconst createUserFormSchema = z.object({\n  name: z\n    .string()\n    .min(2, 'Password must be at least 2 characters long')\n    .transform((name) =>\n      name\n        .trim()\n        .split(' ')\n        .map((word) => {\n          return word[0].toLocaleUpperCase().concat(word.substring(1))\n        })\n        .join(' '),\n    ),\n  email: z\n    .string()\n    .email('Invalid e-mail format')\n    .nonempty('E-mail is required'),\n  birthdate: z.string().nonempty('Date of birth is mandatory'),\n  cpf: z.string().length(11, 'CPF mus have 11 digits'),\n})\n\ntype CreateUserFormData = z.infer<typeof createUserFormSchema>\n\nexport const ClientRegistrationModal = ({\n  isOpen,\n  onClose,\n}: ClientRegistrationModalProps) => {\n  const {\n    register,\n    handleSubmit,\n    formState: { errors, isSubmitting },\n    reset,\n  } = useForm<CreateUserFormData>({\n    mode: 'all',\n    resolver: zodResolver(createUserFormSchema),\n  })\n\n  // High-order function\n  function createUser(data: CreateUserFormData) {\n    console.log(data)\n  }\n\n  function resetForm() {\n    onClose()\n    reset()\n  }\n\n  console.log(errors)\n\n  return (\n    <Modal title=\"Cadastro de Cliente\" isOpen={isOpen} onClose={resetForm}>\n      <form onSubmit={handleSubmit(createUser)}>\n        <div className=\"flex flex-col space-y-6\">\n          <Input\n            label=\"Nome\"\n            type=\"text\"\n            id=\"name\"\n            placeholder=\"Enter your name\"\n            {...register('name')}\n            error={errors.name?.message}\n          />\n\n          <Input\n            label=\"Email\"\n            type=\"email\"\n            id=\"email\"\n            placeholder=\"Enter your e-mail\"\n            {...register('email')}\n            error={errors.email?.message}\n          />\n\n          <Input\n            label=\"Data de Nascimento\"\n            type=\"date\"\n            id=\"birthdate\"\n            {...register('birthdate')}\n            error={errors.birthdate?.message}\n          />\n\n          <Input\n            label=\"CPF\"\n            type=\"text\"\n            id=\"cpf\"\n            placeholder=\"Enter your CPF\"\n            {...register('cpf')}\n            error={errors.cpf?.message}\n          />\n        </div>\n        <div className=\"mt-4 flex items-center justify-between\">\n          <button\n            className=\"mt-4 rounded bg-green-500 px-4 py-2 font-bold text-white transition-all ease-in hover:bg-green-700\"\n            type=\"submit\"\n          >\n            Cadastrar\n          </button>\n          <button\n            type=\"reset\"\n            className=\"mt-4 rounded bg-zinc-500 px-4 py-2 font-bold text-white transition-all ease-in hover:bg-zinc-700\"\n            onClick={resetForm}\n            disabled={isSubmitting}\n          >\n            Cancelar\n          </button>\n        </div>\n      </form>\n    </Modal>\n  )\n}\n```\n\n```text\nname: z.string().min(2, 'The name needs at least 2 characters')\n```\n\n```text\nname: z.string().min(2,{ message: 'The name needs at least 2 characters' })\n```\n\n```text\nimport { type DetailedHTMLProps, type InputHTMLAttributes } from \"react\";\nimport {\n  type FieldErrors,\n  type FieldValues,\n  type Path,\n  type UseFormRegister,\n} from \"react-hook-form\";\n\ninterface InputProps<FormData extends FieldValues>\n  extends DetailedHTMLProps<\n    InputHTMLAttributes<HTMLInputElement>,\n    HTMLInputElement\n  > {\n  label: string;\n  name: Path<FormData>;\n  register: UseFormRegister<FormData>;\n  errors: FieldErrors<FormData>;\n}\n\nexport const Input = <FormData extends FieldValues>({\n  label,\n  name,\n  errors,\n  register,\n  ...rest\n}: InputProps<FormData>) => {\n  const error = errors?.[name]?.message as string | undefined;\n\n  return (\n    <div className=\"flex flex-col\">\n      <label\n        className=\"mb-2 block text-sm font-bold text-zinc-700\"\n        htmlFor={rest.id}\n      >\n        {label}\n      </label>\n      <input\n        type=\"text\"\n        className={`appearance-none rounded-md border border-zinc-300 px-3 py-2 leading-tight shadow-sm focus:border-zinc-500 focus:outline-none\n        ${error ? \"border-red-500\" : \"border-zinc-300\"}`}\n        {...rest}\n        {...register(name)}\n      />\n      {error && <span className=\"text-xs text-red-500\">{error}</span>}\n    </div>\n  );\n};\n```\n\n```text\n<Input\n  label=\"Nome\"\n  type=\"text\"\n  placeholder=\"Enter your name\"\n  name=\"name\"\n  errors={errors}\n  register={register}\n/>\n\n<Input\n  label=\"Email\"\n  type=\"email\"\n  name=\"email\"\n  placeholder=\"Enter your e-mail\"\n  errors={errors}\n  register={register}\n/>\n// ... and so forth\n```\n\n```text\nname: z\n    .string()\n    .min(2, 'Password must be at least 2 characters long')\n```\n\n```text\nname: z\n    .string({ required_error: 'Passoword is required' })\n    .min(2, 'Password must be at least 2 characters long')\n```\n\n```text\nconst onFormError:SubmitErrorHandler<CreateUserFormData> = (e) => {\n   console.log(e)\n}\n\n// Pass down this function in the handleSubmit\n<form onSubmit={handleSubmit(createUser, onFormError)}>\n```\n\n```text\nInput\n```\n\n```text\n{...register(\"name\")}\n```\n\n```text\n<input />\n```\n\n```text\n{...register(\"name\")}\n```\n\n```text\nregister\n```\n\n```text\nInputForm\n```\n\n```text\nname\n```\n\n```text\nregister\n```\n\n```text\nname\n```\n\n```text\nzod\n```\n\n```text\nreact-hook-form\n```\n\n```text\nmin()\n```\n\n```text\nz.string()\n```\n\n```text\nrequired_error\n```\n\n```text\nstring()\n```\n\n```text\nempty\n```\n\n```text\nreact-hook-form\n```\n\n```text\nhandleSubmit\n```\n\n```text\n<Input\n  label=\"Nome\"\n  type=\"text\"\n  placeholder=\"Enter your name\"\n  name=\"name\"\n  errors={errors[\"name\"] && `${(errors[\"name\"] as DeepMap<FieldValues, FieldError>).message}`}\n  register={register}\n/>\n```\n\n```text\nzod\n```\n\n```text\nreact-hook-form\n```\n\n```text\nRequired\n```\n\n```text\nerrors={errors[\"name\"] && `${(errors[\"name\"] as DeepMap<FieldValues, FieldError>).message}`}\n```\n\n```text\nDeepMap\n```\n\n```text\nreact-hook-form\n```","metadata":{"transformedAt":"2026-08-18T18:33:48.868Z","totalAnswersIncluded":1,"totalCodeBlocksIncluded":34,"totalLines":519,"estimatedTokens":2529}}54{"id":"stack-78036454","source":"stackoverflow","questionId":78036454,"title":"How to validate Zod Object depending on value of parent object","tags":["reactjs","forms","validation","zod"],"text":"Title: How to validate Zod Object depending on value of parent object\nTags: reactjs, forms, validation, zod\nSource: Stack Overflow\n\nQuestion:\nI have a zod schema like this:\n\n```\nexport const memberSchema = z\n .object({\n name: z.string().min(3),\n lastname: z.string().min(3),\n nationality: zCountries,\n birthdate: z.date(),\n email: z.string().email(),\n tutor: z\n .object({\n name: z.string(),\n lastname: z.string(),\n documentType: zDocumentationType,\n documentValue: z.string(),\n email: z.string().email(),\n phone: z.string().regex(/^\\d{9}$/)\n })\n }).refine((data) => .....)\n```\n\nIs it possible to validate tutor object is required only if birthdate is under 18 ?\nBecause if member is +18 this fields are not needed.\n\nI know how to validate a field depending of another one in refine function, but I don't know how to validate and entire object...\n\n**EXAMPLE:**\n\n- { birthdate: '20/02/2015'} -> ALL Fields in `tutor` has to be filled and passing zod tutor object validation\n\n- {birthdate: '09/05/1988' } -> Tutor object is undefined and returns true.\n\n========================================\n\nTop Answer:\nYou can use a `superRefine` call to add issues to the overall object. For example:\n\n```\nexport const memberSchema = z\n .object({\n name: z.string().min(3),\n lastname: z.string().min(3),\n nationality: zCountries,\n birthdate: z.date(),\n email: z.string().email(),\n tutor: tutorSchema.optional(),\n })\n .superRefine((obj, ctx) => {\n const ageInYears = getAgeInYears(obj.birthdate);\n if (ageInYears Note that going from the `Date` object to their age in years is potentially non-trivial, so I've left that as an exercise for the reader.\n\nThe main trick is to make the tutor field optional, and then to use the refine to say, \"no actually it must be defined if the user is over 18\".\n\n### A note on types\n\nUnfortunately, this approach does not give you any firmer type guarantees once you know that the user is under 18. If you want the type system to track this for you, you could split the types along the `birthdate` and use `z.brand` to attach that additional information, but it may be more trouble than it's worth.\n\n========================================\n\nCode:\n```text\nexport const memberSchema = z\n  .object({\n    name: z.string().min(3),\n    lastname: z.string().min(3),\n    nationality: zCountries,\n    birthdate: z.date(),\n    email: z.string().email(),\n    tutor: z\n      .object({\n        name: z.string(),\n        lastname: z.string(),\n        documentType: zDocumentationType,\n        documentValue: z.string(),\n        email: z.string().email(),\n        phone: z.string().regex(/^\\d{9}$/)\n      })\n  }).refine((data) => .....)\n```\n\n```text\ntutor\n```\n\n```text\nexport const memberSchema = z\n  .object({\n    name: z.string().min(3),\n    lastname: z.string().min(3),\n    nationality: zCountries,\n    birthdate: z.date(),\n    email: z.string().email(),\n    tutor: z.union([\n      z.object({\n        name: zTutorString,\n        lastname: zTutorString,\n        document: zTutorString,\n        email: zTutorString.email(),\n        phone: zTutorString.regex(/^\\d{9}$/)\n      }),\n      z.undefined()\n    ])\n  })\n  .superRefine((data, ctx) => {\n    const validation =\n      data.birthdate.getFullYear() + 18 < new Date().getFullYear() ||\n      (data.birthdate.getFullYear() + 18 > new Date().getFullYear() && data.tutor !== undefined)\n    if (!validation) {\n      tutorFields.forEach((field) => {\n        if (!data.tutor || (data.tutor && !data.tutor[field as keyof typeof data.tutor])) {\n          ctx.addIssue({\n            code: z.ZodIssueCode.custom,\n            message: i18n.t('validation.required_tutor'),\n            path: ['tutor', field]\n          })\n        }\n      })\n    }\n  })\n```\n\n```text\nz.union\n```\n\n```text\nobject\n```\n\n```text\nundefined\n```\n\n```js\nexport const memberSchema = z\n  .object({\n    name: z.string().min(3),\n    lastname: z.string().min(3),\n    nationality: zCountries,\n    birthdate: z.date(),\n    email: z.string().email(),\n    tutor: tutorSchema.optional(),\n  })\n  .superRefine((obj, ctx) => {\n    const ageInYears = getAgeInYears(obj.birthdate);\n    if (ageInYears < 18 && obj.tutor === undefined) {\n      ctx.addIssue({\n        code: \"custom\",\n        message: \"Members under the age of 18 must have a tutor\",\n      });\n    }\n  });\n\nconsole.log(\n  memberSchema.safeParse({\n    name: \"Test\",\n    lastname: \"Testerson\",\n    nationality: \"USA\",\n    birthdate: new Date(\"2010-1-1\"), // Some date less than 18 years ago\n    email: \"test@example.com\",\n  })\n); // Logs failure with custom message\n\nconsole.log(\n  memberSchema.safeParse({\n    name: \"Test\",\n    lastname: \"Testerson\",\n    nationality: \"USA\",\n    birthdate: new Date(\"2010-1-1\"), // Some date less than 18 years ago\n    email: \"test@example.com\",\n    tutor: {\n      name: \"Tutor\",\n      lastname: \"Some tutor\",\n      phone: undefined,\n      email: undefined,\n      documentType: undefined,\n      documentValue: undefined,\n    },\n  })\n); // Logs success\n```\n\n```text\nsuperRefine\n```\n\n```text\nDate\n```\n\n```text\nbirthdate\n```\n\n```text\nz.brand\n```\n\n========================================\n\nComments:\n- Thanks @Souperman but maybe my tutor object with z.unions is wrong, I include undefined because it can be undefined if member is +18, but if the member is under 18 all fields in tutor has to be REQUIRED and passing the object validation, not only one field filled. I Edit my question\n- I've been looking for this solution for hours! Thanks so much!","metadata":{"transformedAt":"2026-08-18T18:33:48.868Z","totalAnswersIncluded":1,"totalCodeBlocksIncluded":11,"totalLines":209,"estimatedTokens":1361}}55{"id":"stack-76031747","source":"stackoverflow","questionId":76031747,"title":"Typescript: Zod expected string, received undefined","tags":["node.js","typescript","express","zod"],"text":"Title: Typescript: Zod expected string, received undefined\nTags: node.js, typescript, express, zod\nSource: Stack Overflow\n\nQuestion:\nzod is throwing the following error 3 times when i try to submit my req.body data to prisma orm (im using Insomnia):\n\n```\nZodError: [\n {\n \"code\": \"invalid_type\",\n \"expected\": \"string\",\n \"received\": \"undefined\",\n \"path\": [\n \"name\"\n ],\n \"message\": \"Required\"\n },\n```\n\nthis is the prisma client model:\n\n```\nmodel Client {\n id String @id @default(uuid())\n email String @unique\n name String\n password String\n created_at DateTime @default(now())\n updated_at DateTime @updatedAt\n reviews ProductReview[] @relation(\"client\")\n adm Boolean @default(false)\n\n @@map(\"clients\")\n}\n```\n\nthis is the route:\n\n```\nconst authController = new AuthController();\n\nrouter.route('/register').post(authController.registerClient)\n```\n\nthis is the controller with the registerClient function, that is the one that is throwing the zod error:\n\n```\nexport class AuthController {\n async registerClient(req: Request, res: Response) {\n const createClientBody = z.object({\n name: z.string(),\n email: z.string(),\n password: z.string(),\n });\n const { name } = createClientBody.parse(req.body); // this lines\n const { email } = createClientBody.parse(req.body); // this lines\n const { password } = createClientBody.parse(req.body); // this lines\n\n const response = await prisma.client.create({\n data: {\n name,\n email,\n password\n },\n });\n\n return res.status(201).send({ response });\n };\n}\n```\n\n========================================\n\nCode:\n```text\nZodError: [\n  {\n    \"code\": \"invalid_type\",\n    \"expected\": \"string\",\n    \"received\": \"undefined\",\n    \"path\": [\n      \"name\"\n    ],\n    \"message\": \"Required\"\n  },\n```\n\n```text\nmodel Client {\n  id         String          @id @default(uuid())\n  email      String          @unique\n  name       String\n  password   String\n  created_at DateTime        @default(now())\n  updated_at DateTime        @updatedAt\n  reviews    ProductReview[] @relation(\"client\")\n  adm        Boolean         @default(false)\n\n  @@map(\"clients\")\n}\n```\n\n```text\nconst authController = new AuthController();\n\nrouter.route('/register').post(authController.registerClient)\n```\n\n```text\nexport class AuthController {\n    async registerClient(req: Request, res: Response) {\n        const createClientBody = z.object({\n            name: z.string(),\n            email: z.string(),\n            password: z.string(),\n        });\n        const { name } = createClientBody.parse(req.body); // this lines\n        const { email } = createClientBody.parse(req.body); // this lines\n        const { password } = createClientBody.parse(req.body); // this lines\n\n        const response = await prisma.client.create({\n            data: {\n                name,\n                email,\n                password\n            },\n        });\n\n        return res.status(201).send({ response });\n    };\n}\n```\n\n```text\nname: z.string().nullish(),\n```\n\n========================================\n\nComments:\n- If you add `console.log(req.body)` before the parse lines, what do you get?\n- i get {} (the req.body is not working)","metadata":{"transformedAt":"2026-08-18T18:33:48.868Z","totalAnswersIncluded":0,"totalCodeBlocksIncluded":5,"totalLines":143,"estimatedTokens":778}}56{"id":"stack-73310317","source":"stackoverflow","questionId":73310317,"title":"What is the difference between z.optional(z.string()) and z.ostring() of zod?","tags":["javascript","zod"],"text":"Title: What is the difference between z.optional(z.string()) and z.ostring() of zod?\nTags: javascript, zod\nSource: Stack Overflow\n\nQuestion:\nTo make any schema optional, I've seen that zod provides two methods: z.optional(z.string()) and z.ostring().\nI wonder what is the difference between them?\nAnd what should I use for most cases?\n\n========================================\n\nTop Answer:\n**The two ways are the same.**\n\n`z.ostring()` and the like are *shortcuts*. They are equivalent in function to wrapping the normal type with `z.optional()` or chaining `.optional()`.\nIn fact, they are implemented internally using the chained `.optional()`.\n\n========================================\n\nCode:\n```text\nconst ostring = () => stringType().optional();\n```\n\n```text\nconst optionalString = z.string().optional(); // string | undefined\n\n// equivalent to\nz.optional(z.string());\n```\n\n```text\nz.ostring()\n```\n\n```text\nz.optional()\n```\n\n```text\n.optional()\n```\n\n```text\n.optional()\n```\n\n========================================\n\nComments:\n- I don't see `ostring` anywhere in the docs\n- that's true, but when you using the latest version of zod, you can use it as an alternative for the z.optional()","metadata":{"transformedAt":"2026-08-18T18:33:48.869Z","totalAnswersIncluded":1,"totalCodeBlocksIncluded":6,"totalLines":52,"estimatedTokens":298}}57{"id":"stack-75880688","source":"stackoverflow","questionId":75880688,"title":"Is Zod able to parse content of JSON files?","tags":["zod"],"text":"Title: Is Zod able to parse content of JSON files?\nTags: zod\nSource: Stack Overflow\n\nQuestion:\nThis might be a duplicate of Zod: Parse external JSON file\n\nI have a function that expects a JSON string and parses it to a given type, inferred by a Zod schema\n\n```\nconst createConfigurationFromJson = (content: string): Configuration => {\n const rawConfiguration = JSON.parse(content);\n\n return configurationSchema.parse(rawConfiguration);\n};\n```\n\nThis function might throw if the JSON content is invalid JSON or Zod throws a parse error. Without using another third party library, is it possible to let Zod parse the JSON string? So I can be sure there can only be a Zod error?\n\n========================================\n\nTop Answer:\nThere doesn't seem to be a package for that. In theory, such a package would do barely more than what you're already doing.\n\nMaybe you could surround the json parsing with a try catch block, and turn the generic error into a zod error?\n\n========================================\n\nCode:\n```text\nconst createConfigurationFromJson = (content: string): Configuration => {\n  const rawConfiguration = JSON.parse(content);\n\n  return configurationSchema.parse(rawConfiguration);\n};\n```\n\n```js\nconst configurationSchema = z.object({\n  name: z.string(),\n  version: z.string(),\n  description: z.string(),\n});\n\ntype Configuration = z.infer<typeof configurationSchema>;\n\nconst createConfigurationFromJson = (content: string): Configuration => {\n  return z\n    .string()\n    .transform((_, ctx) => {\n      try {\n        return JSON.parse(content);\n      } catch (error) {\n        ctx.addIssue({\n          code: z.ZodIssueCode.custom,\n          message: 'invalid json',\n        });\n        return z.never;\n      }\n    })\n    .pipe(configurationSchema)\n    .parse(content);\n};\n```\n\n```js\nconst configuration1 = createConfigurationFromJson(`{\n  \"name\": \"my-app\",\n  \"version\": \"1.0.0\",\n  \"description\": \"My awesome app\"\n}`);\n\nconst configuration2 = createConfigurationFromJson(`{\n  \"banana\": \"🍌\"\n}`);\n\nconst configuration3 = createConfigurationFromJson(`{\n  fiadsjfoiajsdoivjdaoij\n`);\n```\n\n```js\nconfiguration1 {\n  name: \"my-app\",\n  version: \"1.0.0\",\n  description: \"My awesome app\"\n}\nconfiguration2 159 |     const json = JSON.stringify(obj, null, 2);\n160 |     return json.replace(/\"([^\"]+)\":/g, \"$1:\");\n161 | };\n162 | class ZodError extends Error {\n163 |     constructor(issues) {\n164 |         super();\n            ^\nZodError: [\n  {\n    \"code\": \"invalid_type\",\n    \"expected\": \"string\",\n    \"received\": \"undefined\",\n    \"path\": [\n      \"name\"\n    ],\n    \"message\": \"Required\"\n  },\n  {\n    \"code\": \"invalid_type\",\n    \"expected\": \"string\",\n    \"received\": \"undefined\",\n    \"path\": [\n      \"version\"\n    ],\n    \"message\": \"Required\"\n  },\n  {\n    \"code\": \"invalid_type\",\n    \"expected\": \"string\",\n    \"received\": \"undefined\",\n    \"path\": [\n      \"description\"\n    ],\n    \"message\": \"Required\"\n  }\n]\n errors: [\n  {\n    \"code\": \"invalid_type\",\n    \"expected\": \"string\",\n    \"received\": \"undefined\",\n    \"path\": [\n      \"name\"\n    ],\n    \"message\": \"Required\"\n  },\n  {\n    \"code\": \"invalid_type\",\n    \"expected\": \"string\",\n    \"received\": \"undefined\",\n    \"path\": [\n      \"version\"\n    ],\n    \"message\": \"Required\"\n  },\n  {\n    \"code\": \"invalid_type\",\n    \"expected\": \"string\",\n    \"received\": \"undefined\",\n    \"path\": [\n      \"description\"\n    ],\n    \"message\": \"Required\"\n  }\n]\n\n      at new ZodError (/Users/sgunter/code/zod-parse-json/node_modules/zod/lib/index.mjs:164:8)\n      at /Users/sgunter/code/zod-parse-json/node_modules/zod/lib/index.mjs:537:30\n      at parse (/Users/sgunter/code/zod-parse-json/node_modules/zod/lib/index.mjs:636:14)\n      at /Users/sgunter/code/zod-parse-json/index.ts:46:25\n\nconfiguration3 159 |     const json = JSON.stringify(obj, null, 2);\n160 |     return json.replace(/\"([^\"]+)\":/g, \"$1:\");\n161 | };\n162 | class ZodError extends Error {\n163 |     constructor(issues) {\n164 |         super();\n            ^\nZodError: [\n  {\n    \"code\": \"custom\",\n    \"message\": \"invalid json\",\n    \"fatal\": true,\n    \"path\": []\n  }\n]\n errors: [\n  {\n    \"code\": \"custom\",\n    \"message\": \"invalid json\",\n    \"fatal\": true,\n    \"path\": []\n  }\n]\n\n      at new ZodError (/Users/sgunter/code/zod-parse-json/node_modules/zod/lib/index.mjs:164:8)\n      at /Users/sgunter/code/zod-parse-json/node_modules/zod/lib/index.mjs:537:30\n      at parse (/Users/sgunter/code/zod-parse-json/node_modules/zod/lib/index.mjs:636:14)\n      at /Users/sgunter/code/zod-parse-json/index.ts:55:25\n```\n\n```text\nconfigurationSchema\n```\n\n```text\ncontent\n```\n\n```text\n.pipe\n```\n\n```text\nconfigurationSchema\n```\n\n========================================\n\nComments:\n- why is `.custom((data) => {` not using the data arg? also, is this running `JSON.parse` twice? that's a heavy operation, I wonder if we could use a JSON schema to validate instead of using parse twice...","metadata":{"transformedAt":"2026-08-18T18:33:48.869Z","totalAnswersIncluded":1,"totalCodeBlocksIncluded":8,"totalLines":208,"estimatedTokens":1217}}58{"id":"stack-78156760","source":"stackoverflow","questionId":78156760,"title":"How to represent a partial record in zod?","tags":["typescript","zod"],"text":"Title: How to represent a partial record in zod?\nTags: typescript, zod\nSource: Stack Overflow\n\nQuestion:\nI need to represent a `Partial>` with zod.\n\nIn TypeScript, we can do this easily:\n\n```\ntype SomeEnum = 'one' | 'two'\ntype MyRecord = Record\ntype MyRecordPartial = Partial\n```\n\nWith zod, we can represent the enum and record, but not the partial record?\n\n```\nconst SomeEnum = z.enum(['one', 'two'])\nconst MyRecord = z.record(SomeEnum, z.boolean());\nconst MyRecordPartial = MyRecord.partial() // This is not a method for Records.\n```\n\nWhat's the idoimatic way of doing this?\n\n========================================\n\nTop Answer:\nZod records **were** partial by default in Zod v3.\n\nIn v4, To achieve optional keys, use `z.partialRecord()`.\n\nRead the docs on \"Records\" and the migration guide.\n\n========================================\n\nCode:\n```js\ntype SomeEnum = 'one' | 'two'\ntype MyRecord = Record<SomeNum, boolean>\ntype MyRecordPartial = Partial<MyRecord>\n```\n\n```js\nconst SomeEnum = z.enum(['one', 'two'])\nconst MyRecord = z.record(SomeEnum, z.boolean());\nconst MyRecordPartial = MyRecord.partial() // This is not a method for Records.\n```\n\n```text\nPartial<Record<SomeEnum, boolean>>\n```\n\n```text\nimport { z } from 'zod'\n\nconst SomeEnum = z.enum(['one', 'two'])\n\nconst MyRecord = z.record(SomeEnum, z.boolean());\n\ntype MyRecordType = z.infer<typeof MyRecord>\n// {\n//    one?: boolean | undefined;\n//    two?: boolean | undefined;\n// }\n\nconst testA: MyRecordType = { one: true } // fine\n```\n\n```text\nz.partialRecord()\n```\n\n========================================\n\nComments:\n- by why it does not allow const MyRecord = z.record(SomeEnum, z.boolean()).catch({});\n- This answer is outdated github.com/colinhacks/zod/issues/2623#issuecomment-289687458&zwnj;&#8203;1","metadata":{"transformedAt":"2026-08-18T18:33:48.869Z","totalAnswersIncluded":1,"totalCodeBlocksIncluded":5,"totalLines":78,"estimatedTokens":442}}59{"id":"stack-74157068","source":"stackoverflow","questionId":74157068,"title":"zod conditional validation base on form field","tags":["reactjs","typescript","react-hook-form","zod"],"text":"Title: zod conditional validation base on form field\nTags: reactjs, typescript, react-hook-form, zod\nSource: Stack Overflow\n\nQuestion:\nI have a `status = 'DRAFT' | 'READY'` enum field in my form, is it possible to change validation in `zod` lib based on value of this field?\n\n```\n// validation passed\n{\n name: \"John\",\n surname: null,\n status: \"DRAFT\"\n}\n\n// validation failed\n{\n name: \"John\",\n surname: null,\n status: \"READY\"\n}\n```\n\nSo esentialy if `status === \"READY\"` remove `.min(1)` from here\n\n```\nconst schema = z.object({\n name: z.string(),\n surname: z.string().min(1),\n status: z.enum([\"READY\", \"DRAFT\"])\n});\n```\n\n========================================\n\nTop Answer:\nThis works\n\n```\nconst schema = z.union([\n z.object({\n name: z.string(),\n surname: z.string(),\n status: z.literal(\"DRAFT\"),\n }),\n z.object({\n name: z.string(),\n surname: z.string().min(1),\n status: z.literal(\"READY\"),\n }),\n]);\n```\n\n========================================\n\nCode:\n```text\n// validation passed\n{\n  name: \"John\",\n  surname: null,\n  status: \"DRAFT\"\n}\n\n// validation failed\n{\n  name: \"John\",\n  surname: null,\n  status: \"READY\"\n}\n```\n\n```text\nconst schema = z.object({\n  name: z.string(),\n  surname: z.string().min(1),\n  status: z.enum([\"READY\", \"DRAFT\"])\n});\n```\n\n```text\nstatus = 'DRAFT' | 'READY'\n```\n\n```text\nzod\n```\n\n```text\nstatus === \"READY\"\n```\n\n```text\n.min(1)\n```\n\n```js\n// placing shared fields in one place to avoid repetition\nconst base = z.object({\n  name: z.string(),\n});\n\nconst schema = z.discriminatedUnion(\n  'status',\n  [\n    z.object({\n      status: z.literal(\"DRAFT\"),\n      surname: z.string(),\n    }).merge(base),\n    z.object({\n      status: z.literal(\"READY\"),\n      surname: z.string().min(1),\n    }).merge(base),\n  ],\n);\n```\n\n```text\nunion\n```\n\n```text\ndiscriminatedUnion\n```\n\n```text\nunion\n```\n\n```text\nDRAFT\n```\n\n```text\nsurname\n```\n\n```text\noptional\n```\n\n```text\nstatus\n```\n\n```text\n\"READY\"\n```\n\n```text\nunion\n```\n\n```text\nsurname\n```\n\n```text\nstring | undefined\n```\n\n```text\nstatus\n```\n\n```text\nconst schema = z.union([\n  z.object({\n    name: z.string(),\n    surname: z.string(),\n    status: z.literal(\"DRAFT\"),\n  }),\n  z.object({\n    name: z.string(),\n    surname: z.string().min(1),\n    status: z.literal(\"READY\"),\n  }),\n]);\n```","metadata":{"transformedAt":"2026-08-18T18:33:48.869Z","totalAnswersIncluded":1,"totalCodeBlocksIncluded":20,"totalLines":179,"estimatedTokens":562}}60{"id":"stack-73715295","source":"stackoverflow","questionId":73715295,"title":"React hook form with zod resolver optional field","tags":["typescript","next.js","react-hook-form","zod"],"text":"Title: React hook form with zod resolver optional field\nTags: typescript, next.js, react-hook-form, zod\nSource: Stack Overflow\n\nQuestion:\nI want to make a form with React-hook-form and zod resolver where all fields are optional but fields still required despite making them optional in zod schema:\n\n```\nconst schema = z.object({\n name: z.string().min(3).max(50).optional(),\n description: z.string().min(3).max(255).optional(),\n image: clientImageSchema.optional(),\n })\nconst {...} = useForm({ resolver: zodResolver(schema) })\n```\n\nwhen submitting the form with blank inputs it validates fields as required. Where is the error or the mistake ?\n\n========================================\n\nTop Answer:\nAs it says in the documentation, you must make a union between your schema and z.literal(\"\"), so it doesn't trigger any error if the value is an empty string.\nSee example.\n\n```\nconst optionalUrl = z.union([z.string().url().nullish(), z.literal(\"\")]);\n```\n\n========================================\n\nCode:\n```js\nconst schema = z.object({\n    name: z.string().min(3).max(50).optional(),\n    description: z.string().min(3).max(255).optional(),\n    image: clientImageSchema.optional(),\n  })\nconst {...} = useForm({ resolver: zodResolver(schema) })\n```\n\n```text\nconst schema = z.object({\n  // Watch out, z.preprocess takes two arguments\n  foo: z.preprocess(\n    (foo) => {\n      // this line won't work\n      // return foo\n\n      // this line will work, dunno why\n      // console.log(typeof email)\n\n      // I'm using this\n      if (!foo || typeof foo !== 'string') return undefined\n      return foo === '' ? undefined : foo\n    },\n    z\n      .string()\n      .email({\n        message: 'Please correct your email address',\n      })\n      .optional(),\n  ),\n})\n```\n\n```text\n.preprocess()\n```\n\n```text\nconst defaultValues = {\n  name: '',\n  /** rest */\n}\n\n  useForm<ToolCreateApiData>({\n    resolver: zodResolver(schema),\n    defaultValues,\n  });\n```\n\n```text\ndefaultValues\n```\n\n```text\nuseForm\n```\n\n```js\nconst optionalUrl = z.union([z.string().url().nullish(), z.literal(\"\")]);\n```\n\n```text\nconst { handleSubmit, setValue, getValues, reset} = useForm<DataType>({\n    resolver: zodResolver(DataSchema),\n});\n\nconst preSubmit = () => {\n    const values = getValues();\n    if (values.name === \"\") setValue(\"name\", undefined);\n};\n\nconst submitForm = (data: DataType) => {\n    console.log(data);\n    reset();\n};\n\n<form onSubmit={(e) => {\n    preSubmit();\n    void handleSubmit(submitForm)(e);\n}}>\n    //...form fields\n</form>\n```\n\n```text\nconst form = useForm<z.infer<typeof updateUserSchema>>({\n    resolver: zodResolver(updateUserSchema),\n    reValidateMode : \"onChange\",\n    defaultValues: {\n        username: Data.User?.username ?? \"\", \n        email: Data.User?.email ?? \"\",\n        password: undefined\n    },\n});\n```\n\n========================================\n\nComments:\n- In my case, I fixed adding `undefined` as the default value","metadata":{"transformedAt":"2026-08-18T18:33:48.869Z","totalAnswersIncluded":1,"totalCodeBlocksIncluded":9,"totalLines":132,"estimatedTokens":731}}61{"id":"stack-76399524","source":"stackoverflow","questionId":76399524,"title":"Could not find a declaration file for module '@hookform/resolvers/zod'","tags":["javascript","reactjs","typescript","zod"],"text":"Title: Could not find a declaration file for module '@hookform/resolvers/zod'\nTags: javascript, reactjs, typescript, zod\nSource: Stack Overflow\n\nQuestion:\nIm trying to use zod with react-hook-form but the import hook form resolver gives the error below\n\nCould not find a declaration file for module '@hookform/resolvers/zod'. '/pradeep/projects/react/safe-zone/node_modules/@hookform/resolvers/zod/dist/zod.mjs' implicitly has an 'any' type.\n\nhttps://i.sstatic.net/dKOCI.png\n\n========================================\n\nTop Answer:\nCheck the version of `@hookform/resolvers` being installed.\nfor me it was installing version `2.*.*` instead of the latest version `^3.9.0`.\n\nI updated the `@hookform/resolvers` version manually in the *package.json*. Then run `yarn install`.\n\n========================================\n\nCode:\n```text\nnpm i -save-dev @hookform/resolvers\n```\n\n```text\n@hookform/resolvers\n```\n\n```text\n2.*.*\n```\n\n```text\n^3.9.0\n```\n\n```text\n@hookform/resolvers\n```\n\n```text\nyarn install\n```\n\n========================================\n\nComments:\n- arunmichaeldsouza.com/blog/aliasing-module-paths-in-node-js\n- you can try adding a paths configuration in your package.json file to create an alias for the module import.\n- \"compilerOptions\": { \"baseUrl\": \".\", \"paths\": { \"@hookform/resolvers/zod\": [\"./node_modules/@hookform/resolvers/zod/dist/zod.mjs\"] } }\n- I tried this but no luck.\n- now will the build will be created? as we have installed it in dev dependency? issues in production?","metadata":{"transformedAt":"2026-08-18T18:33:48.869Z","totalAnswersIncluded":1,"totalCodeBlocksIncluded":6,"totalLines":54,"estimatedTokens":374}}62{"id":"stack-77167264","source":"stackoverflow","questionId":77167264,"title":"Display error messages in multiple locations using zod","tags":["react-hook-form","zod"],"text":"Title: Display error messages in multiple locations using zod\nTags: react-hook-form, zod\nSource: Stack Overflow\n\nQuestion:\nI have a form created with zod.\nBoth are optional inputs, but I want to make sure that both are input if one is input.\nAnd I want to display the error message on both sides.\n\nSo I wrote the code as below.\n\n```\nconst schema = z.object({\n samplea: z.string().optional(),\n sampleb: z.string().optional(),\n}).refine(\n (args) => {\n if (args.samplea || args.sampleb) {\n return args.samplea && args.sampleb ? true : false;\n }\n return true;\n },\n {\n message: \"If you enter, please enter both\",\n path: [\"samplea\", \"sampleb\"],\n }\n);\n\n...\n\n samplea\n \n\n sampleb\n \n\n```\n\nThere is a problem that the error message can only be displayed for \"sampleb\".\nI would like to know how to make both \"samplea\" and \"sampleb\" error and display error messages for both.\n\n========================================\n\nCode:\n```text\nconst schema = z.object({\n  samplea: z.string().optional(),\n  sampleb: z.string().optional(),\n}).refine(\n  (args) => {\n    if (args.samplea || args.sampleb) {\n      return args.samplea && args.sampleb ? true : false;\n    }\n    return true;\n  },\n  {\n    message: \"If you enter, please enter both\",\n    path: [\"samplea\", \"sampleb\"],\n  }\n);\n\n...\n\n<Box>\n  <FormLabel>samplea</FormLabel>\n  <TextField\n    type=\"text\"\n    {...register(\"samplea\")}\n    error={!!errors.samplea}\n    helperText={errors.samplea?.message}\n  />\n</Box>\n\n<Box>\n  <FormLabel>sampleb</FormLabel>\n  <TextField\n    type=\"text\"\n    {...register(\"sampleb\")}\n    error={!!errors.sampleb}\n    helperText={errors.sampleb?.message}\n  />\n</Box>\n```\n\n```text\nconst schema = z\n  .object({\n    samplea: z.string().optional(),\n    sampleb: z.string().optional(),\n  })\n  .superRefine((args, ctx) => {\n    if (!args.samplea && !args.sampleb) {\n      ctx.addIssue({\n        code: z.ZodIssueCode.custom,\n        path: [\"samplea\"],\n        fatal: true,\n        message: \"If you enter, please enter both\",\n      });\n      ctx.addIssue({\n        code: z.ZodIssueCode.custom,\n        path: [\"sampleb\"],\n        fatal: true,\n        message: \"If you enter, please enter both\",\n      });\n    }\n});\n```\n\n```text\nsuperRefine\n```\n\n```text\nsuperRefine\n```\n\n```text\nargs\n```\n\n```text\nctx\n```\n\n```text\nsuperRefine\n```\n\n```text\nif\n```\n\n```text\n!args.samplea && !args.sampleb\n```\n\n```text\nctx.addIssue\n```\n\n```text\ncode\n```\n\n```text\npath\n```\n\n```text\nfatal\n```\n\n```text\nmessage\n```\n\n========================================\n\nComments:\n- Perhaps 'samplea' does not have an error message because its not erroring out. Have you tried checking the internals of the zod error object.","metadata":{"transformedAt":"2026-08-18T18:33:48.869Z","totalAnswersIncluded":0,"totalCodeBlocksIncluded":14,"totalLines":160,"estimatedTokens":659}}63{"id":"stack-76354177","source":"stackoverflow","questionId":76354177,"title":"How to infer Zod type in JSDoc (without TypeScript)","tags":["javascript","jsdoc","zod"],"text":"Title: How to infer Zod type in JSDoc (without TypeScript)\nTags: javascript, jsdoc, zod\nSource: Stack Overflow\n\nQuestion:\nSuppose I have the schema in javascript:\n\n```\nimport {z} from \"zod\";\nlet personSchema = z.object({\n name: z.string(),\n id: z.number()\n});\n```\n\nnow I want to use the type somewhere else:\n\n```\n/** \n* @param {{name:string, id:number}} person \n* but should instead be something like this?:\n* @param {???(typeof z)[\"infer\"]???} person \n*/\nfunction (person) {\n person.name; // autocompletions and vscode linting should work here\n // do stuff\n}\n```\n\nOf course this would be easy in typescript, but I'm trying to use JSDOC since the project doesn't allow TypeScript.\n\n========================================\n\nTop Answer:\nThis works:\n\n```\n/** \n* @param {ReturnType} person\n*/ \nfunction (person) {\n person.name; // autocompletions and vscode linting should work here\n // do stuff\n}\n```\n\nAlthough this works, I suspect there is a better solution.\n\n========================================\n\nCode:\n```js\nimport {z} from \"zod\";\nlet personSchema = z.object({\n  name: z.string(),\n  id: z.number()\n});\n```\n\n```js\n/** \n* @param {{name:string, id:number}} person \n* but should instead be something like this?:\n* @param {???(typeof z)[\"infer\"]<typeof personSchema>???} person \n*/\nfunction (person) {\n person.name; // autocompletions and vscode linting should work here\n // do stuff\n}\n```\n\n```js\nimport {z} from \"zod\";\n\n/** \n* @typedef {z.infer<typeof PersonSchema>} Person\n*/ \nlet PersonSchema = z.object({\n  name: z.string(),\n  id: z.number()\n});\n\n/** \n* @param {Person} person\n*/ \nfunction (person) {\n person.name; // autocompletions and vscode linting should work here\n // do stuff\n}\n```\n\n```text\nz.infer\n```\n\n```js\n/** \n* @param {ReturnType<(typeof personSchema)[\"parse\"]>} person\n*/ \nfunction (person) {\n person.name; // autocompletions and vscode linting should work here\n // do stuff\n}\n```\n\n```js\nexport const personSchema = z.object({ /* ... */ });\n// If you're using eslint, it may complain here but you can ignore\n// the redeclaration complaint\nexport type personSchema = z.infer<typeof personSchema>;\n```\n\n```js\n/**\n * @param {personSchema} person\n */\nfunction (person) {\n  person.name;\n};\n```\n\n```text\npersonSchema\n```\n\n========================================\n\nComments:\n- Following your cue, you could also define a Person type after the schema: `@typedef {ReturnType} Person`... then use `@param {Person} person` in the function's jsdoc annotation.\n- Doesn't `z.infer` require a typescript compile step though?\n- Right. I guess I wasn't sure what OP's exact set up is. I was thinking he was importing his schema from TypeScript code into JavaScript, but I think your interpretation is probably right and I would prefer your answer anyway since it avoids overloading the name and give a better name to the type.\n- interesting that z.infer is bundled from the import. thank you!\n- Yes it's weird to see Javascript code (obj.function + `typeof`) executed into comments. But after all that's compilation/lining code to help DX; it is not code that will ever be executed by the application.\n- That works great, but many of them are classified as type any. when i hover overr my schema : let ENV: { ACCESS_TOKEN_SECRET?: any; REFRESH_TOKEN_SECRET?: any; ACCESS_TOKEN_SECRET_EXPIRE?: any; REFRESH_TOKEN_SECRET_EXPIRE?: any; COOKIE_MAX_AGE?: number; DATABASE_URI?: any; DATABASE_NAME?: any; NODE_ENV?: \"development\" | \"production\"; ALLOWED_ORIGINS?: any; PORT?: number; }","metadata":{"transformedAt":"2026-08-18T18:33:48.869Z","totalAnswersIncluded":1,"totalCodeBlocksIncluded":8,"totalLines":134,"estimatedTokens":871}}64{"id":"stack-73570071","source":"stackoverflow","questionId":73570071,"title":"Merge of two enums zod","tags":["zod"],"text":"Title: Merge of two enums zod\nTags: zod\nSource: Stack Overflow\n\nQuestion:\nI have 2 enums, `const Option1 = z.enum([\"option1\"])` and `const Option2 = z.enum([\"option2\"])`.\nI want to merge these two into `z.ZodEnum`\n\nThe only way I came up with so far is\n\n```\nexport const Options = z.enum([\n ...Option1.options,\n ...Option2.options,\n]);\n// Options.options is now [\"option1\", \"option2\"]\n```\n\nIs there any zod native way to do this?\n\n========================================\n\nTop Answer:\nThere's an extension of @mizerlou's answer for `nativeEnum`.\n\nSimilar to\n\n```\nconst allOptions = [...Option1.options, ...Option2.options] as const\n```\n\nYou have to do\n\n```\nconst Options = { ...Option1, ...Option2 } as const;\n```\n\nSomething like this\n\n```\nconst Option1 = { OPTION1: 'Option1' } as const;\nconst Option1Enum = z.nativeEnum(Option1);\ntype Option1 = z.infer;\n\nconst Option2 = { OPTION2: 'Option2' } as const;\nconst Option2Enum = z.nativeEnum(Option2);\ntype Option2 = z.infer;\n\nconst Options = { ...Option1, ...Option2 } as const;\nconst OptionsEnum = z.nativeEnum(Options);\ntype Options = z.infer;\n```\n\n========================================\n\nCode:\n```text\nexport const Options = z.enum([\n  ...Option1.options,\n  ...Option2.options,\n]);\n// Options.options is now [\"option1\", \"option2\"]\n```\n\n```text\nconst Option1 = z.enum([\"option1\"])\n```\n\n```text\nconst Option2 = z.enum([\"option2\"])\n```\n\n```text\nz.ZodEnum<[\"option1\", \"option2\"]>\n```\n\n```js\nconst allOptions = [...Option1.options, ...Option2.options]\n```\n\n```js\nconst allOptions = [...Option1.options, ...Option2.options] as const\n```\n\n```js\nconst Options = z.enum([...Option1.options, ...Option2.options] as const)\n```\n\n```text\nallOptions\n```\n\n```text\n(\"option1\" | \"option2\")[]\n```\n\n```text\nallOptions\n```\n\n```text\nallOptions\n```\n\n```text\n[\"option1\", \"option2\"]\n```\n\n```text\nz.ZodEnum<[\"option1\", \"option2\"]>\n```\n\n```js\nconst allOptions = [...Option1.options, ...Option2.options] as const\n```\n\n```js\nconst Options = { ...Option1, ...Option2 } as const;\n```\n\n```js\nconst Option1 = { OPTION1: 'Option1' } as const;\nconst Option1Enum = z.nativeEnum(Option1);\ntype Option1 = z.infer<typeof Option1Enum>;\n\nconst Option2 = { OPTION2: 'Option2' } as const;\nconst Option2Enum = z.nativeEnum(Option2);\ntype Option2 = z.infer<typeof Option2Enum>;\n\nconst Options = { ...Option1, ...Option2 } as const;\nconst OptionsEnum = z.nativeEnum(Options);\ntype Options = z.infer<typeof OptionsEnum>;\n```\n\n```text\nnativeEnum\n```","metadata":{"transformedAt":"2026-08-18T18:33:48.869Z","totalAnswersIncluded":1,"totalCodeBlocksIncluded":17,"totalLines":137,"estimatedTokens":614}}65{"id":"stack-79162864","source":"stackoverflow","questionId":79162864,"title":"How to prevent Form Field Reset on Validation Error When Using useActionState and Zod Validation in React 19/Next.js 15","tags":["reactjs","forms","next.js","zod","server-action"],"text":"Title: How to prevent Form Field Reset on Validation Error When Using useActionState and Zod Validation in React 19/Next.js 15\nTags: reactjs, forms, next.js, zod, server-action\nSource: Stack Overflow\n\nQuestion:\nI'm working with **React 19** and **Next.js 15**. I want to create a form that lets users update the payment amount and currency. Each currency has a different maximum payment limit, and if a user enters a value over that limit, the form should display an error message without resetting other fields. I'm using `useActionState` for handling form actions and Zod for data validation.\n\n### Expected User Flow\n\nUser opens the form with a default payment value of 100 Euros.\n\nUser selects \"Yen\" as the currency and enters 200 as the payment value.\n\nThe form displays an error message indicating that the payment exceeds the allowed maximum for Yen.\nhttps://i.sstatic.net/oVfwLOA4.png\n\n- User only has to update the payment value (without re-selecting the currency).\n\n### Issue\n\nCurrently, when the form displays a validation error:\n\n- The currency resets to the first option in the currency list (instead of retaining the user’s selection) - not even to the default of the state?.\n\n- The user has to re-select the currency before changing the payment amount.\n\n**How can I prevent this reset, so the currency selection persists on validation errors? I’d like to keep using useActionState and server actions for handling form submission and validation.**\n\n### Code\n\nBelow is a minimal code example that reproduces this issue.i\n\nPage:\n\n```\n\"use client\";\nimport React, { useActionState, useState } from \"react\";\nimport { useFormStatus } from \"react-dom\";\nimport { currencies } from \"./data-schema\";\nimport { actionPaymentSubmit } from \"./actionPaymentSubmit\";\n\nfunction SubmitButton() {\n const { pending } = useFormStatus();\n return {pending ? \"Pending...\" : \"Submit\"};\n}\n\nexport default function Home() {\n const [payment, setPayment] = useState(100);\n const [currency, setCurrency] = useState(\"EUR\");\n const [state, formAction] = useActionState(actionPaymentSubmit, {\n data: {\n payment,\n currency,\n },\n });\n\n return (\n \n \n Payment\n setPayment(Number(e.target.value))}\n />\n Currency\n setCurrency(e.target.value)}\n >\n {currencies.map((currency) => (\n \n {currency.label}\n \n ))}\n \n \n {state.errors?.payment && {state.errors.payment}}\n {state.message && {state.message}}\n \n \n );\n}\n```\n\nData:\n\n```\nimport { z } from \"zod\";\n\nexport const currencies = [\n { label: \"US Dollar\", value: \"USD\" },\n { label: \"Euro\", value: \"EUR\" },\n { label: \"British Pound\", value: \"GBP\" },\n { label: \"Japanese Yen\", value: \"JPY\" },\n { label: \"Australian Dollar\", value: \"AUD\" },\n];\n\nexport const PaymentSchema = z\n .object({\n payment: z.number().int().positive(),\n currency: z.enum(currencies.map((currency) => currency.value)),\n })\n .superRefine((data, ctx) => {\n const maxPayments = {\n USD: 10,\n EUR: 90,\n GBP: 80,\n JPY: 100,\n AUD: 120,\n };\n\n const maxPayment = maxPayments[data.currency];\n\n if (data.payment > maxPayment) {\n ctx.addIssue({\n code: \"custom\",\n path: [\"payment\"],\n message: `The maximum payment for ${data.currency} is ${maxPayment}.`,\n });\n }\n });\n```\n\nAction:\n\n```\n\"use server\";\n\nimport { PaymentSchema } from \"./data-schema\";\n\nexport async function actionPaymentSubmit(previousState, formData) {\n await new Promise((resolve) => setTimeout(resolve, 300));\n\n const paymentData = {\n currency: formData.get(\"currency\"),\n payment: Number(formData.get(\"payment\")),\n };\n\n const validated = PaymentSchema.safeParse(paymentData);\n\n if (!validated.success) {\n const errors = validated.error.issues.reduce((acc, issue) => {\n acc[issue.path[0]] = issue.message;\n return acc;\n }, {});\n return {\n errors,\n data: paymentData,\n };\n }\n\n return {\n message: \"Payment was done!\",\n data: paymentData,\n };\n}\n```\n\n========================================\n\nTop Answer:\nI had a similar concern,\nMy solution was to simply add default values from `useActionState` and on my server actions i can return an object the overrides the `state` with the entered values.\n\nHere is an example:\n\n```\nconst [state, formAction] = useActionState(action, {\n fields: {\n code: '',\n name: '',\n country: '',\n }\n});\n```\n\nOne of the inputs:\n\n```\n\n \n\n```\n\nIt has a default value from the `useActionState` hook.\n\nAnd on my server action:\n\n```\ntry {\n insertCurrency(code, name, country);\n } catch (error) {\n return {\n error: error.message,\n fields: {\n code, name, country\n }\n }\n }\n```\n\nAs mentioned above, the server action returns an object that has fields which matches the initial state set of the hook, the will make the default value set the the values submitted by the user.\n\nTool tip: This is the full server action function\n\n```\nexport async function createCurrency(_, formData) {\n const code = formData.get('code');\n const name = formData.get('name');\n const country = formData.get('country');\n\n // ... try catch block\n}\n```\n\n========================================\n\nCode:\n```text\n\"use client\";\nimport React, { useActionState, useState } from \"react\";\nimport { useFormStatus } from \"react-dom\";\nimport { currencies } from \"./data-schema\";\nimport { actionPaymentSubmit } from \"./actionPaymentSubmit\";\n\nfunction SubmitButton() {\n  const { pending } = useFormStatus();\n  return <button type=\"submit\">{pending ? \"Pending...\" : \"Submit\"}</button>;\n}\n\nexport default function Home() {\n  const [payment, setPayment] = useState(100);\n  const [currency, setCurrency] = useState(\"EUR\");\n  const [state, formAction] = useActionState(actionPaymentSubmit, {\n    data: {\n      payment,\n      currency,\n    },\n  });\n\n  return (\n    <main>\n      <form action={formAction}>\n        <label htmlFor=\"payment\">Payment</label>\n        <input\n          id=\"payment_ammount\"\n          min=\"0\"\n          type=\"number\"\n          name=\"payment\"\n          value={payment}\n          onChange={(e) => setPayment(Number(e.target.value))}\n        />\n        <label htmlFor=\"currency\">Currency</label>\n        <select\n          key={currency}\n          id=\"currency\"\n          name=\"currency\"\n          value={currency}\n          onChange={(e) => setCurrency(e.target.value)}\n        >\n          {currencies.map((currency) => (\n            <option key={currency.value} value={currency.value}>\n              {currency.label}\n            </option>\n          ))}\n        </select>\n        <SubmitButton />\n        {state.errors?.payment && <div>{state.errors.payment}</div>}\n        {state.message && <div>{state.message}</div>}\n      </form>\n    </main>\n  );\n}\n```\n\n```text\nimport { z } from \"zod\";\n\nexport const currencies = [\n  { label: \"US Dollar\", value: \"USD\" },\n  { label: \"Euro\", value: \"EUR\" },\n  { label: \"British Pound\", value: \"GBP\" },\n  { label: \"Japanese Yen\", value: \"JPY\" },\n  { label: \"Australian Dollar\", value: \"AUD\" },\n];\n\nexport const PaymentSchema = z\n  .object({\n    payment: z.number().int().positive(),\n    currency: z.enum(currencies.map((currency) => currency.value)),\n  })\n  .superRefine((data, ctx) => {\n    const maxPayments = {\n      USD: 10,\n      EUR: 90,\n      GBP: 80,\n      JPY: 100,\n      AUD: 120,\n    };\n\n    const maxPayment = maxPayments[data.currency];\n\n    if (data.payment > maxPayment) {\n      ctx.addIssue({\n        code: \"custom\",\n        path: [\"payment\"],\n        message: `The maximum payment for ${data.currency} is ${maxPayment}.`,\n      });\n    }\n  });\n```\n\n```text\n\"use server\";\n\nimport { PaymentSchema } from \"./data-schema\";\n\nexport async function actionPaymentSubmit(previousState, formData) {\n  await new Promise((resolve) => setTimeout(resolve, 300));\n\n  const paymentData = {\n    currency: formData.get(\"currency\"),\n    payment: Number(formData.get(\"payment\")),\n  };\n\n  const validated = PaymentSchema.safeParse(paymentData);\n\n  if (!validated.success) {\n    const errors = validated.error.issues.reduce((acc, issue) => {\n      acc[issue.path[0]] = issue.message;\n      return acc;\n    }, {});\n    return {\n      errors,\n      data: paymentData,\n    };\n  }\n\n  return {\n    message: \"Payment was done!\",\n    data: paymentData,\n  };\n}\n```\n\n```text\nuseActionState\n```\n\n```text\n\"use client\";\nimport React, { useActionState } from \"react\";\nimport { useFormStatus } from \"react-dom\";\nimport { currencies } from \"./data-schema\";\nimport { actionPaymentSubmit } from \"./actionPaymentSubmit\";\n\nfunction SubmitButton() {\n  const { pending } = useFormStatus();\n  return <button type=\"submit\">{pending ? \"Pending...\" : \"Submit\"}</button>;\n}\n\nexport default function Home() {\n  const [state, formAction] = useActionState(actionPaymentSubmit, {\n    data: {\n      payment: 100,\n      currency: \"EUR\",\n    },\n  });\n\n  return (\n    <main>\n      <form action={formAction}>\n        <label htmlFor=\"payment\">Payment</label>\n        <input\n          id=\"payment_ammount\"\n          min=\"0\"\n          type=\"number\"\n          name=\"payment\"\n          defaultValue={state.data.payment}\n        />\n        <label htmlFor=\"currency\">Currency</label>\n        <select\n          key={state.data.currency}\n          id=\"currency\"\n          name=\"currency\"\n          defaultValue={state.data.currency}\n        >\n          {currencies.map((currency) => (\n            <option key={currency.value} value={currency.value}>\n              {currency.label}\n            </option>\n          ))}\n        </select>\n        <SubmitButton />\n        {state.errors?.payment && <div>{state.errors.payment}</div>}\n        {state.message && <div>{state.message}</div>}\n      </form>\n    </main>\n  );\n}\n```\n\n```text\nconst [state, formAction] = useActionState(action, {\n        fields: {\n            code: '',\n            name: '',\n            country: '',\n        }\n});\n```\n\n```text\n<div>\n     <Box \n          name=\"code\" \n          type=\"text\" \n          placeholder=\"Code\" \n          defaultValue={state.fields.code} />\n</div>\n```\n\n```text\ntry {\n        insertCurrency(code, name, country);\n    } catch (error) {\n        return {\n            error: error.message,\n            fields: {\n                code, name, country\n            }\n        }\n    }\n```\n\n```text\nexport async function createCurrency(_, formData) {\n    const code = formData.get('code');\n    const name = formData.get('name');\n    const country = formData.get('country');\n\n    // ... try catch block\n}\n```\n\n```text\nuseActionState\n```\n\n```text\nstate\n```\n\n```text\nuseActionState\n```\n\n========================================\n\nComments:\n- Wouldn't that auto fill the inputs with default values? A user would like those to be empty on the first page load, right?\n- @McFlurriez Yes, but this form is part of \"Edit table row\" functionality, when there is an already predefined value, that user can change. I dropped this from description to narrow down the issue =)","metadata":{"transformedAt":"2026-08-18T18:33:48.869Z","totalAnswersIncluded":1,"totalCodeBlocksIncluded":12,"totalLines":458,"estimatedTokens":2665}}66{"id":"stack-77958464","source":"stackoverflow","questionId":77958464,"title":"How to create a record with required keys?","tags":["typescript","zod"],"text":"Title: How to create a record with required keys?\nTags: typescript, zod\nSource: Stack Overflow\n\nQuestion:\nI'm trying to create a dictionary like zod schema for an object that has many keys, defined elsewhere, and they all have the same value type. And all keys are required.\n\n```\nconst KeysSchema = z.enum(['a', 'b', 'c', /*...*/]) // long key list\nconst ObjSchema = z.record(KeysSchema, z.number())\n```\n\nBut the yielded type is:\n\n```\n{\n a?: number | undefined;\n b?: number | undefined;\n c?: number | undefined;\n}\n```\n\nBut what I want is:\n\n```\n{\n a: number;\n b: number;\n c: number;\n}\n```\n\nI want: `Record`\n\nbut it's giving me: `Partial>`\n\nAnd I can't call `z.record(...).required()` because that's not a thing for zod records.\n\nHow can I make a record type with required keys?\n\nSee Typescript playground\n\n========================================\n\nTop Answer:\nBased on Alex Wayne’s answer, I created a universal function for usage:\n\n```\nfunction createRequiredObjSchema(\n keysSchema: z.ZodEnum,\n valueSchema: V\n) {\n return z.record(keysSchema, valueSchema).refine((obj): obj is Record> =>\n keysSchema.options.every((key) => obj[key] != null),\n );\n}\n```\n\nSmall example how it is works:\n\n```\nconst requiredRecord = createRequiredObjSchema(KeysSchema, z.string())\n\ntype RequiredRecordExample = z.infer;\n/*\ntype RequiredRecordExample = {\n a: string;\n b: string;\n c: string;\n}\n*/\n```\n\nSee Playground\n\n**UPDATE:**\n\nhttps://zod.dev/api#records\n\n**Zod 4** — In Zod 4, if you pass a `z.enum` as the first argument to `z.record()`, Zod will exhaustively check that all enum values exist in the input as keys. This behavior agrees with TypeScript:\n\n```\ntype MyRecord = Record;const myRecord: MyRecord = { a: \"foo\", b: \"bar\" }; // ✅const myRecord: MyRecord = { a: \"foo\" }; // ❌ missing required key `b`\n```\n\nIn Zod 3, exhaustiveness was not checked. To replicate the old behavior, use `z.partialRecord()`.\n\n========================================\n\nCode:\n```text\nconst KeysSchema = z.enum(['a', 'b', 'c', /*...*/]) // long key list\nconst ObjSchema = z.record(KeysSchema, z.number())\n```\n\n```text\n{\n    a?: number | undefined;\n    b?: number | undefined;\n    c?: number | undefined;\n}\n```\n\n```text\n{\n    a: number;\n    b: number;\n    c: number;\n}\n```\n\n```text\nRecord<'a', 'b', 'c', number>\n```\n\n```text\nPartial<Record<\"a\" | \"b\" | \"c\", number>>\n```\n\n```text\nz.record(...).required()\n```\n\n```text\n.refine((obj): obj is Required<typeof obj> =>\n    KeysSchema.options.every((key) => obj[key] != null),\n  )\n```\n\n```text\n.refine()\n```\n\n```text\nKeysSchema\n```\n\n```text\nfunction createRequiredObjSchema<\n  K extends string,\n  V extends z.ZodTypeAny\n>(\n  keysSchema: z.ZodEnum<[K, ...K[]]>,\n  valueSchema: V\n) {\n  return z.record(keysSchema, valueSchema).refine((obj): obj is Record<K, z.infer<V>> =>\n    keysSchema.options.every((key) => obj[key] != null),\n  );\n}\n```\n\n```text\nconst requiredRecord = createRequiredObjSchema(KeysSchema, z.string())\n\ntype RequiredRecordExample = z.infer<typeof requiredRecord>;\n/*\ntype RequiredRecordExample = {\n    a: string;\n    b: string;\n    c: string;\n}\n*/\n```\n\n```text\ntype MyRecord = Record<\"a\" | \"b\", string>;const myRecord: MyRecord = { a: \"foo\", b: \"bar\" }; // ✅const myRecord: MyRecord = { a: \"foo\" }; // ❌ missing required key `b`\n```\n\n```text\nz.enum\n```\n\n```text\nz.record()\n```\n\n```text\nz.partialRecord()\n```\n\n========================================\n\nComments:\n- github.com/colinhacks/zod/issues/2623\n- Thank you! Surprisingly that gave me a `Required>>`, so I tweaked it a little bit: `.refine((obj): obj is typeof obj extends Partial ? R : never => KeysSchema.options.every((key) => obj[key] != null))`","metadata":{"transformedAt":"2026-08-18T18:33:48.869Z","totalAnswersIncluded":1,"totalCodeBlocksIncluded":15,"totalLines":185,"estimatedTokens":907}}67{"id":"stack-76533416","source":"stackoverflow","questionId":76533416,"title":"Use zod discriminatedUnion with an enum discriminator without typing out all enum possibilities","tags":["typescript","validation","enums","discriminated-union","zod"],"text":"Title: Use zod discriminatedUnion with an enum discriminator without typing out all enum possibilities\nTags: typescript, validation, enums, discriminated-union, zod\nSource: Stack Overflow\n\nQuestion:\nI'm trying to use zod schema validation to validate some data that has different constraints based on the value of an enumeration field (prisma generated enum type). Basically it can take these two shapes:\n\n```\n{ discriminatorField: \"VAL1\", otherField: \"any string\" }\n\n{ discriminatorField: \"any other allowed string besides VAL1\", otherField: undefined }\n```\n\nIt seems this can be done with `z.discriminatedUnion()` in the following way:\n\n```\nconst schema = z.discriminatedUnion(\"discriminatorField\", [\n z.object({ discriminatorField: z.literal(\"VAL1\"), otherField: z.string()}),\n z.object({ discriminatorField: z.literal(\"VAL2\"), otherField: z.string().optional()}),\n // ... have to type out all possible enum values as literal conditions here?\n])\n```\n\nThis works, but you have to type out all possible enum values to discriminate on. I tried using `z.nativeEnum(MyEnum)` instead of `z.literal(\"VAL2\")` in the code above, but zod then complains that the values are overlapping, which is of course true, but I hoped it would just use the first case that matches.\n\n========================================\n\nCode:\n```js\n{ discriminatorField: \"VAL1\", otherField: \"any string\" }\n\n{ discriminatorField: \"any other allowed string besides VAL1\", otherField: undefined }\n```\n\n```js\nconst schema = z.discriminatedUnion(\"discriminatorField\", [\n   z.object({ discriminatorField: z.literal(\"VAL1\"), otherField: z.string()}),\n   z.object({ discriminatorField: z.literal(\"VAL2\"), otherField: z.string().optional()}),\n   // ... have to type out all possible enum values as literal conditions here?\n])\n```\n\n```text\nz.discriminatedUnion()\n```\n\n```text\nz.nativeEnum(MyEnum)\n```\n\n```text\nz.literal(\"VAL2\")\n```\n\n```js\nconst schema = z.discriminatedUnion(\"discriminatorField\", [\n  z.object({ discriminatorField: z.literal(\"VAL1\"), otherField: z.string() }),\n  ...Object.values(MyEnum)\n    .filter((enum) => enum !== \"VAL1\")\n    .map((enum) =>\n      z.object({\n        discriminatorField: z.literal(enum),\n        otherField: z.string().optional(),\n      }),\n    ),\n]);\n```\n\n========================================\n\nComments:\n- The whole point of a discriminated union is that the type of the rest of the object differs based on that `discriminatorField`. So you'd have have to list individually them anyway to provide that type for all the other fields.\n- The type does differ. But only for 1 possible value of about 24. Having to write out 24 cases, of which 23 are all the same is a lot of repeated work that I would like to avoid.","metadata":{"transformedAt":"2026-08-18T18:33:48.869Z","totalAnswersIncluded":0,"totalCodeBlocksIncluded":6,"totalLines":73,"estimatedTokens":679}}68{"id":"stack-77816383","source":"stackoverflow","questionId":77816383,"title":"How to set the error message in zod refine method?","tags":["javascript","typescript","zod"],"text":"Title: How to set the error message in zod refine method?\nTags: javascript, typescript, zod\nSource: Stack Overflow\n\nQuestion:\nI have the following Zod schema:\n\n```\nconst createApSchema = z\n .object({\n name: z.string().min(1).max(32),\n isActive: z.boolean().default(true),\n description: z.string().max(200).optional(),\n ip: z.string().refine(validator.isIP),\n accessMode: AccessModeEnum,\n apiUsername: z.string().optional(),\n apiPassword: z.string().optional(),\n apiVersion: ApiVersionEnum,\n community: z.string().optional(),\n })\n .refine((data) => {\n // check to see if AP type is snmp to force the community field\n const isSnmp = data.accessMode !== AccessModeEnumMap[AccessModeEnum.enum.mikrotikApi]\n if (isSnmp && !data.community) throw new Error('community string is required!')\n // check to see if AP type is mikrotik to force the api credentials fields\n if (!isSnmp && (!data.apiUsername || !data.apiPassword)) throw new Error('api username and password are required!')\n if (!isSnmp && !data.apiVersion) throw new Error('api version is required!')\n return true\n })\n```\n\nAnd the rule says, if you choose \"mikrotikApi\" as a value for the `accessMode` property, then the fields `apiUsername` & `apiPassword` & `apiVersion` will be required. Otherwise, if choose for example \"snmp\", then the field `community` will be required.\n\nIt works, however, in the last block in the chain, in the `refine` on the schema object, I am throwing errors in case of a wrong validation. It causes to exit my application. I don't want to exit the app. instead of throwing an error, I want somehow to ***set*** the error, so that I can handle it myself. I just want to specify an error message.\n\nHow to set the error message in zod refine method?\n\n========================================\n\nCode:\n```text\nconst createApSchema = z\n  .object({\n    name: z.string().min(1).max(32),\n    isActive: z.boolean().default(true),\n    description: z.string().max(200).optional(),\n    ip: z.string().refine(validator.isIP),\n    accessMode: AccessModeEnum,\n    apiUsername: z.string().optional(),\n    apiPassword: z.string().optional(),\n    apiVersion: ApiVersionEnum,\n    community: z.string().optional(),\n  })\n  .refine((data) => {\n    // check to see if AP type is snmp to force the community field\n    const isSnmp = data.accessMode !== AccessModeEnumMap[AccessModeEnum.enum.mikrotikApi]\n    if (isSnmp && !data.community) throw new Error('community string is required!')\n    // check to see if AP type is mikrotik to force the api credentials fields\n    if (!isSnmp && (!data.apiUsername || !data.apiPassword)) throw new Error('api username and password are required!')\n    if (!isSnmp && !data.apiVersion) throw new Error('api version is required!')\n    return true\n  })\n```\n\n```text\naccessMode\n```\n\n```text\napiUsername\n```\n\n```text\napiPassword\n```\n\n```text\napiVersion\n```\n\n```text\ncommunity\n```\n\n```text\nrefine\n```\n\n```text\n.superRefine((data, ctx) => {\n    // check to see if AP type is snmp to force the community field\n    const isSnmp = data.accessMode !== AccessModeEnumMap[AccessModeEnum.enum.mikrotikApi]\n    \n    if (isSnmp && !data.community) {\n        ctx.addIssue({\n            code: z.ZodIssueCode.custom,\n            message: 'community string is required!'\n        })\n    }\n\n    // check to see if AP type is mikrotik to force the api credentials fields\n    if (!isSnmp && (!data.apiUsername || !data.apiPassword)) {\n        ctx.addIssue({\n            code: z.ZodIssueCode.custom,\n            message: 'api username and password are required!'\n        })\n    }\n\n\n    if (!isSnmp && !data.apiVersion) {\n        ctx.addIssue({\n            code: z.ZodIssueCode.custom,\n            message: 'api version is required!'\n        })\n    }\n})\n```\n\n```text\nconst mikroApSchema = z.object({\n    accessMode: AccessModeEnum.extract(['mikrotikApi']), // only mikrotikApi\n    apiUsername: z.string(),\n    apiPassword: z.string(),\n    apiVersion: ApiVersionEnum,\n    community: z.string(),\n})\n\nconst otherApSchema = z.object({\n    accessMode: AccessModeEnum.exclude(['mikrotikApi']), // everything but mikrotikApi\n    apiUsername: z.string().optional(),\n    apiPassword: z.string().optional(),\n    apiVersion: ApiVersionEnum,\n    community: z.string().optional(),\n})\n\nconst createApSchema = z.union([mikroApSchema, otherApSchema])\n```\n\n```text\n.superRefine\n```\n\n```text\nsuperRefine\n```\n\n```text\nctx.addIssue\n```\n\n========================================\n\nComments:\n- The second argument to refine is the error, or a function returning the error if the first argument returns false zod.dev/?id=arguments. Don’t throw\n- will I provide a function? then how can I use it?\n- can you give a simple example? I don't think I can provide a simple object or a string as the second argument, right?\n- The examples are right there in the documentation link. You can provide an object or a function that returns an object as a second parameter. zod.dev/?id=customize-error-path. You can’t provide a plain string.\n- I also suggest turning your one refinement into 3 separate refinements, as you have 3 potential errors. You can do it with one refinement, but I think 3 is cleaner\n- @AdamJenkins, I believe the only solution to this is to make them 3 refine method, right?\n- No, it’s not the only solution because the second parameter can be a function. But you’d have to duplicate the logic in both functions, so I think it’s really clean, simple, and testable to implement it with 3 refinements\n- You might want to use a union that is discriminated on the `accessMode`, instead of `refine` with custom error messages\n- @Bergi, wow this one is cool\n- @AdamJenkins, yes that's what i was thinking\n- I think this will work, I will try it","metadata":{"transformedAt":"2026-08-18T18:33:48.869Z","totalAnswersIncluded":0,"totalCodeBlocksIncluded":12,"totalLines":164,"estimatedTokens":1424}}69{"id":"stack-76342806","source":"stackoverflow","questionId":76342806,"title":"Zod validation schema make field required based on another array field","tags":["reactjs","validation","zod"],"text":"Title: Zod validation schema make field required based on another array field\nTags: reactjs, validation, zod\nSource: Stack Overflow\n\nQuestion:\nI have a Zod validation schema with an array field and a string field:\n\n```\nconst zodSchema = z.object({\n goals: z.array(z.string()).nonempty(\"At least one goal is required\"),\n goals_other: z.string(),\n});\n```\n\nHow do I make the `goals_other` field required ONLY if `goals` array includes the string \"Other\"?\n\nI tried a refine function like the following but it didn't work\n\n```\nconst zodSchema = z\n .object({\n goals: z.array(z.string()).nonempty(\"At least one goal is required\"),\n goals_other: z.string(),\n })\n .refine((data) => (data.goals.includes(\"Other\") ? true : false), {\n message: \"Required, please specify other goals\",\n path: [\"goals_other\"],\n });\n```\n\nAny help is appreciated!\n\n========================================\n\nCode:\n```text\nconst zodSchema = z.object({\n  goals: z.array(z.string()).nonempty(\"At least one goal is required\"),\n  goals_other: z.string(),\n});\n```\n\n```text\nconst zodSchema = z\n  .object({\n    goals: z.array(z.string()).nonempty(\"At least one goal is required\"),\n    goals_other: z.string(),\n  })\n  .refine((data) => (data.goals.includes(\"Other\") ? true : false), {\n    message: \"Required, please specify other goals\",\n    path: [\"goals_other\"],\n  });\n```\n\n```text\ngoals_other\n```\n\n```text\ngoals\n```\n\n```js\nimport { z } from \"zod\";\n\nconst zodSchema = z\n  .object({\n    goals: z.array(z.string()).nonempty(\"At least one goal is required\"),\n    goals_other: z.string().optional() // optional to avoid failing when it's missing\n  })\n  .superRefine(({ goals, goals_other }, ctx) => {\n    // Here we add the extra check to assert the field exists when\n    // the \"Other\" goal is present.\n    if (goals.includes(\"Other\") && goals_other === undefined) {\n      ctx.addIssue({\n        code: \"custom\",\n        message: \"Required, please specify other goals\",\n        path: [\"goals_other\"]\n      });\n    }\n  });\n\nconsole.log(zodSchema.safeParse({\n  goals: ['test'],\n})); // success\nconsole.log(zodSchema.safeParse({\n  goals: ['Other'],\n})); // failure\nconsole.log(zodSchema.safeParse({\n  goals: ['Other'],\n  goals_other: 11,\n})); // failure (because goals_other is not a string)\nconsole.log(zodSchema.safeParse({\n  goals: ['Other'],\n  goals_other: 'test',\n})); // success\n```\n\n```js\nzodSchema.safeParse({\n  goals: ['test'],\n  goals_other: 11,\n}); // Failure\n```\n\n```js\nconst zodSchema = z\n  .object({\n    goals: z.array(z.string()).nonempty(\"At least one goal is required\"),\n    goals_other: z.unknown(),\n  })\n  .superRefine(({ goals, goals_other }, ctx) => {\n    if (goals.includes(\"Other\")) {\n      if (goals_other === undefined) {\n        ctx.addIssue({\n          code: \"custom\",\n          message: \"Required, please specify other goals\",\n          path: [\"goals_other\"]\n        });\n      } else if (typeof goals_other !== 'string') {\n        ctx.addIssue({\n          code: 'custom',\n          message: 'expected a string',\n          path: ['goals_other'],\n        });\n      }\n    }\n  });\n```\n\n```text\ngoals_other\n```\n\n```text\n'Other'\n```\n\n```text\ngoals_other\n```\n\n```text\nstring | undefined\n```\n\n```text\ngoals_other\n```\n\n```text\n\"Other\"\n```\n\n```text\nother_goals\n```\n\n```text\nunknown\n```\n\n```text\ntransform\n```\n\n```text\ngoals_other\n```\n\n```text\n\"Other\"\n```","metadata":{"transformedAt":"2026-08-18T18:33:48.869Z","totalAnswersIncluded":0,"totalCodeBlocksIncluded":18,"totalLines":173,"estimatedTokens":831}}70{"id":"stack-74122007","source":"stackoverflow","questionId":74122007,"title":"Require none or both fields with Zod","tags":["typescript","zod"],"text":"Title: Require none or both fields with Zod\nTags: typescript, zod\nSource: Stack Overflow\n\nQuestion:\nI have the properties `startDate` and `endDate` in a Zod schema. I'd like to verify that either:\n\n- None of them are set\n\n- Both of them are set\n\nI.e. if only `startDate` or only `endDate` is set, parsing will fail.\n\nThe schema looks like:\n\n```\nexport const MediumSchema = z.object({\n ImageSetID: z.number().int().positive(),\n ...\n CampaignStartDate: z.date().nullable(),\n CampaignEndDate: z.date().nullable(),\n Url: z.string().url().transform((url) => new URL(url)),\n CDNUrl: z.string().url().transform((url) => new URL(url))\n});\n```\n\nHow do I achieve this?\n\n========================================\n\nCode:\n```text\nexport const MediumSchema = z.object({\n    ImageSetID: z.number().int().positive(),\n    ...\n    CampaignStartDate: z.date().nullable(),\n    CampaignEndDate: z.date().nullable(),\n    Url: z.string().url().transform((url) => new URL(url)),\n    CDNUrl: z.string().url().transform((url) => new URL(url))\n});\n```\n\n```text\nstartDate\n```\n\n```text\nendDate\n```\n\n```text\nstartDate\n```\n\n```text\nendDate\n```\n\n```js\nimport { z } from 'zod';\n\nconst schema = z.object({\n  startDate: z.date(),\n  endDate: z.date(),\n});\n\nconst schemaBothUndefined = z.object({\n  startDate: z.undefined(),\n  endDate: z.undefined(),\n});\n\nconst bothOrNeither = schema.or(schemaBothUndefined);\n\nconsole.log(bothOrNeither.safeParse({})); // success\nconsole.log(bothOrNeither.safeParse({\n  startDate: new Date(),\n  endDate: new Date(),\n})); // success\nconsole.log(bothOrNeither.safeParse({\n  startDate: new Date(),\n})); // failure\n```\n\n```js\nimport { z } from \"zod\";\n\nconst startAndEnd = z.object({\n  CampaignStartDate: z.date(),\n  CampaignEndDate: z.date(),\n});\nconst neitherStartNorEnd = z.object({\n  CampaignStartDate: z.undefined(),\n  CampaignEndDate: z.undefined(),\n});\n\nconst CampaignDates = startAndEnd.or(neitherStartNorEnd);\n\nexport const MediumSchema = z.object({\n  id: z.string(),\n}).and(CampaignDates);\n\nconsole.log(MediumSchema.safeParse({ id: '11' })); // success \nconsole.log(MediumSchema.safeParse({ \n  id: '11',\n  CampaignStartDate: new Date(),\n  CampaignEndDate: new Date()\n})); // Success\nconsole.log(MediumSchema.safeParse({ \n  id: '11',\n  CampaignEndDate: new Date()\n})); // Failure\n```\n\n```text\nunion\n```\n\n```text\nor\n```\n\n```text\nand\n```\n\n========================================\n\nComments:\n- Thanks for the reply! `startDate` and `endDate` is part of a bigger schema. How do I apply this in a bigger schema? See edited question with schema above.\n- I've added a bit more explanation in response to your edits. Hope this helps!\n- Works just as intended. You've saved me again, thanks!\n- amazing!!!!!!!!!","metadata":{"transformedAt":"2026-08-18T18:33:48.869Z","totalAnswersIncluded":0,"totalCodeBlocksIncluded":10,"totalLines":132,"estimatedTokens":676}}71{"id":"stack-78464328","source":"stackoverflow","questionId":78464328,"title":"How to Extend a Zod Object with Another Object and Pick Certain Entries?","tags":["javascript","typescript","validation","zod"],"text":"Title: How to Extend a Zod Object with Another Object and Pick Certain Entries?\nTags: javascript, typescript, validation, zod\nSource: Stack Overflow\n\nQuestion:\nI'm using Zod, a TypeScript schema validation library, to validate objects in my application. I have a scenario where I need to validate an object with nested properties and extend it with another object while picking only certain entries from the second object.\n\nHere's what I'm trying to achieve:\n\n```\nlogValidation.pick({\n level: true,\n event: true,\n userId: true,\n ipAddress: true,\n statusCode: true,\n}).extend(validation.pick({\n limit: true,\n offset: true\n}))\n```\n\nIn the above code:\n\n`logValidation` represents the schema for validating log objects.\n\nI want to extend `logValidation` with another object containing\npagination parameters (limit and offset).\n\n- However, I want to `pick` only `limit` and `offset` from the second object to extend `logValidation`.\n\nBut this code doesn't work as expected. Zod's extend method doesn't seem to support picking certain entries from the extending object.\n\nIs there a way to achieve this functionality with Zod? I\n\n========================================\n\nCode:\n```text\nlogValidation.pick({\n        level: true,\n        event: true,\n        userId: true,\n        ipAddress: true,\n        statusCode: true,\n}).extend(validation.pick({\n    limit: true,\n    offset: true\n}))\n```\n\n```text\nlogValidation\n```\n\n```text\nlogValidation\n```\n\n```text\npick\n```\n\n```text\nlimit\n```\n\n```text\noffset\n```\n\n```text\nlogValidation\n```","metadata":{"transformedAt":"2026-08-18T18:33:48.869Z","totalAnswersIncluded":0,"totalCodeBlocksIncluded":7,"totalLines":74,"estimatedTokens":381}}72{"id":"stack-73202769","source":"stackoverflow","questionId":73202769,"title":"Validate HTML input date tag using zod with React","tags":["reactjs","zod"],"text":"Title: Validate HTML input date tag using zod with React\nTags: reactjs, zod\nSource: Stack Overflow\n\nQuestion:\nCurrently I have a React-application with a useState object. As the user enters a date into an ``, it stores that value to the useState object.\n\nI am trying to validate the input afterwards with Zod. But it fails since the input is stored as a string, and I am trying to validate the input as a date (`z.date()`).\n\nNow, do I have to, if it's possible, convert the input from a string to a date? Or is it fine storing the date as a string and just change the validation to accept a string?\n\nI guess it depends on how the database is supposed to work. Any tips/recommendations/thoughts on this? What would be your approach and what's the alternatives?\n\n========================================\n\nTop Answer:\nZod added a new functionality where you can force the parsing of the input to the specified type with `coerce` : https://zod.dev/?id=coercion-for-primitives\n\nSince *zod 3.20*, use `z.coerce.date()` to pass the input through `new Date(input)`.\n\n```\nconst dateSchema = z.coerce.date();\ntype DateSchema = z.infer;\n// type DateSchema = Date\n\n/* valid dates */\nconsole.log(dateSchema.safeParse(\"2023-01-10T00:00:00.000Z\").success); // true\nconsole.log(dateSchema.safeParse(\"2023-01-10\").success); // true\nconsole.log(dateSchema.safeParse(\"1/10/23\").success); // true\nconsole.log(dateSchema.safeParse(new Date(\"1/10/23\")).success); // true\n\n/* invalid dates */\nconsole.log(dateSchema.safeParse(\"2023-13-10\").success); // false\nconsole.log(dateSchema.safeParse(\"0000-00-00\").success); // false\n```\n\n(source: https://zod.dev/?id=dates)\n\n========================================\n\nCode:\n```text\n<input type=\"date\" />\n```\n\n```text\nz.date()\n```\n\n```js\nconst dateSchema = z.preprocess((arg) => {\n  if (typeof arg == \"string\" || arg instanceof Date) return new Date(arg);\n}, z.date());\n```\n\n```text\nzod\n```\n\n```text\nDate\n```\n\n```text\nstring\n```\n\n```text\nzod\n```\n\n```text\ndateSchema\n```\n\n```text\nstring\n```\n\n```text\nDate\n```\n\n```text\ndate\n```\n\n```text\nz.date()\n```\n\n```js\nconst dateSchema = z.coerce.date();\ntype DateSchema = z.infer<typeof dateSchema>;\n// type DateSchema = Date\n\n/* valid dates */\nconsole.log(dateSchema.safeParse(\"2023-01-10T00:00:00.000Z\").success); // true\nconsole.log(dateSchema.safeParse(\"2023-01-10\").success); // true\nconsole.log(dateSchema.safeParse(\"1/10/23\").success); // true\nconsole.log(dateSchema.safeParse(new Date(\"1/10/23\")).success); // true\n\n/* invalid dates */\nconsole.log(dateSchema.safeParse(\"2023-13-10\").success); // false\nconsole.log(dateSchema.safeParse(\"0000-00-00\").success); // false\n```\n\n```text\ncoerce\n```\n\n```text\nz.coerce.date()\n```\n\n```text\nnew Date(input)\n```","metadata":{"transformedAt":"2026-08-18T18:33:48.869Z","totalAnswersIncluded":1,"totalCodeBlocksIncluded":16,"totalLines":118,"estimatedTokens":678}}73{"id":"stack-76797356","source":"stackoverflow","questionId":76797356,"title":"Zod nativeEnum type checks enum's value","tags":["typescript","zod"],"text":"Title: Zod nativeEnum type checks enum's value\nTags: typescript, zod\nSource: Stack Overflow\n\nQuestion:\nI am using a zod schema to validate an object with an enum field in it:\n\n```\nenum Colour {\n red: 'Red',\n blue: 'Blue',\n}\n\nconst schema = z.object({\n colour: z.nativeEnum(Colour),\n});\n```\n\nI have input data coming from an api for the colour values as either 'red' or 'blue', and I want to check this with the above schema. However, the above schema's nativeEnum checks according the capitalized cases in the enum, not the enum properties:\n\n```\nenum Colour {\n red: 'Red',\n blue: 'Blue',\n}\n\nconst schema = z.object({\n colour: z.nativeEnum(Colour),\n});\n\nconst rawInput1 = {\n colour: 'red' // should be identified as valid\n};\nconst parsedInput1 = schema.parse(rawInput1); // this fails\n\nconst rawInput2 = {\n colour: 'Red' // should be identified as invalid\n};\nconst parsedInput2 = schema.parse(rawInput2); // this passes\n```\n\nHow can I make zod validate based the property in the enum instead of the value? And why is this happening?\n\nThe reason why I also want to parse the enum properties and I have defined the enum that way is because I want to parse the object and use the `colour` variable to index its string value in the enum: `Colour[parsedInput1.colour]`. This will not be possible if `colour` is the string value.\n\n========================================\n\nTop Answer:\nEasiest way I could do that with zod was,\n\n```\nenum Colour {\n red: 'Red',\n blue: 'Blue',\n}\n\nconst isValidColour: bool = z.nativeEnum(Colour).safeParse(\"Red\").success; // true\n\nconst isValidColour: bool = z.nativeEnum(Colour).safeParse(\"Pink\").success; // false\n```\n\n========================================\n\nCode:\n```text\nenum Colour {\n    red: 'Red',\n    blue: 'Blue',\n}\n\nconst schema = z.object({\n    colour: z.nativeEnum(Colour),\n});\n```\n\n```text\nenum Colour {\n    red: 'Red',\n    blue: 'Blue',\n}\n\nconst schema = z.object({\n    colour: z.nativeEnum(Colour),\n});\n\nconst rawInput1 = {\n    colour: 'red' // should be identified as valid\n};\nconst parsedInput1 = schema.parse(rawInput1); // this fails\n\nconst rawInput2 = {\n    colour: 'Red' // should be identified as invalid\n};\nconst parsedInput2 = schema.parse(rawInput2); // this passes\n```\n\n```text\ncolour\n```\n\n```text\nColour[parsedInput1.colour]\n```\n\n```text\ncolour\n```\n\n```text\nenum Colour {\n    red = 'Red',\n    blue = 'Blue',\n}\n\nconst keys = Object.keys(Colours) // [\"red\", \"blue\"]\n\nconst schema = z.object({\n    colour: z.enum(keys),\n});\n```\n\n```text\ntype KeyUnion = keyof typeof Colour // \"red\" | \"blue\"\n```\n\n```text\nconst keys = Object.keys(Colours) as [keyof typeof Colour]\nconst schema = z.object({\n    colour: z.enum(keys),\n});\n```\n\n```text\n.enum()\n```\n\n```text\nObject.keys()\n```\n\n```text\nkeys\n```\n\n```text\nstring[]\n```\n\n```text\n[\"red\", \"blue\"]\n```\n\n```text\nkeyof typeof\n```\n\n```text\nkeys\n```\n\n```text\nkeys\n```\n\n```text\n[keyof typeof Colour]\n```\n\n```text\nenum Colour {\n    red: 'Red',\n    blue: 'Blue',\n}\n\nconst isValidColour: bool = z.nativeEnum(Colour).safeParse(\"Red\").success; // true\n\nconst isValidColour: bool = z.nativeEnum(Colour).safeParse(\"Pink\").success; // false\n```\n\n========================================\n\nComments:\n- Thanks it is a great hack around it. If only zod could provide an easier way to define enum schemas.\n- I don't think you read the question","metadata":{"transformedAt":"2026-08-18T18:33:48.869Z","totalAnswersIncluded":1,"totalCodeBlocksIncluded":18,"totalLines":184,"estimatedTokens":828}}74{"id":"stack-77130608","source":"stackoverflow","questionId":77130608,"title":"zod \"optional()\" but disallow undefined value","tags":["javascript","typescript","zod"],"text":"Title: zod \"optional()\" but disallow undefined value\nTags: javascript, typescript, zod\nSource: Stack Overflow\n\nQuestion:\nI have a following zod example:\n\n```\nconst objectSchema = z.object({\n optional: z.string().optional(),\n other: z.string(),\n});\n// the current default behavior: \n objectSchema({ other: \"other\" }) //pass.\n objectSchema({ optional: undefined, other: \"other\" }) // pass\n objectSchema({ optional: \"str\", other: \"other\" }) // pass\n```\n\nIn typescript, optional field `key?: string` will be converted to `key?: string | undefined`. But it's strictly different during the runtime check.\nThe previous one during the runtime check could be interpreted as the `optional` must be `string` if it exists, hence `optional: undefined` is an invalid input.\n\nSo, is there any way I can do with zod that makes the `undefined` an invalid input.\n\nhence\n\n```\nobjectSchema({ other: \"other\" }) //pass.\n objectSchema({ optional: undefined, other: \"other\" }) // fail\n objectSchema({ optional: \"str\", other: \"other\" }) // pass\n```\n\nThat's my current attempt, which is fine if there is only one optional field, but it starts to become extremely messy and unusable `(z.object().or().or().or()), basically (the number of optional field)^2 permutation`.\n\n```\nconst objectSchema = z.object({\n optional: z.string(),\n other: z.string(),\n}).strict().or(z.object({\n other: z.string(),\n}).strict());\n```\n\n========================================\n\nCode:\n```js\nconst objectSchema = z.object({\n  optional: z.string().optional(),\n  other: z.string(),\n});\n// the current default behavior: \n  objectSchema({ other: \"other\" }) //pass.\n  objectSchema({ optional: undefined, other: \"other\" }) // pass\n  objectSchema({ optional: \"str\", other: \"other\" }) // pass\n```\n\n```js\nobjectSchema({ other: \"other\" }) //pass.\n  objectSchema({ optional: undefined, other: \"other\" }) // fail\n  objectSchema({ optional: \"str\", other: \"other\" }) // pass\n```\n\n```js\nconst objectSchema = z.object({\n  optional: z.string(),\n  other: z.string(),\n}).strict().or(z.object({\n  other: z.string(),\n}).strict());\n```\n\n```text\nkey?: string\n```\n\n```text\nkey?: string | undefined\n```\n\n```text\noptional\n```\n\n```text\nstring\n```\n\n```text\noptional: undefined\n```\n\n```text\nundefined\n```\n\n```text\n(z.object().or().or().or()), basically (the number of optional field)^2 permutation\n```\n\n```text\n// key is either missing or key exists with type string, cannot be `undefined`\ntype object {\n key?: string;\n}\n```\n\n```text\n// key may or may not exist with the type string or undefined.\ntype object {\n key?: string | undefined;\n}\n```\n\n```text\nif (key in object && typeof obj.key === \"undefined\") { \n   delete obj.key \n }\n```\n\n```text\nzod\n```\n\n```text\nzod\n```\n\n```text\ntypescript\n```\n\n```text\nzod\n```\n\n========================================\n\nComments:\n- What is your use case for differentiating between `optional` not being present and being present with an `undefined` value?\n- I believe there's a TS config option to make `key?: type` different to `key: undefined`, in the way you are asking about. Something about \"strict optional\" or \"exact optional\". Maybe that's what you need?\n- @DarrylNoakes yep, but more for `zod` itself, since the typescript is generated from the `zod`, and the runtime check is following the ts definition, which allows undefined value for that key. I don't need the `optional()` if there is a correct way to handle it.\n- @emeraldsanto sorry, im missing your question? `key: undefined` just cannot be the valid value for many places during the runtime, we cannot expect that piece of data with undefined value will be automatically handled it further down. If zod as a runtime check wouldn't handle this case then I might need to handle it by myself, but maybe there is a way to do it, or I misuse `optional()`?\n- @Yunhai Oh, I misread. I thought Zod was performing the check as you wanted but the types didn't correspond.\n- There isn't really any practical difference between `{a:...}` and `{a:..., b:undefined}` (in both cases, trying to resolve `b` yields undefined). What *actual thing* are you trying to add zod typing for here? What's your use case?\n- @Mike'Pomax'Kamermans , I was trying to either `raise a error` for the undefined value, which sounds impossible based on what you said. Or strip the `b` key away during the parse, either way is fine. Just don't include the `b: undefined` at the end. This might sounds straight forward in this simple case, but it's quite common we have nested object with optional field. then zod will omit a bunch of undefined based on the `optional()` depending on the input. Then it's just not so useful as a validator. Hope you can understand what I'm trying to solve.\n- No, I mean \"what real thing are you working with that requires this kind of typing\", what's your actual real life use-case? (and can you please add that into your post?)\n- @Mike'Pomax'Kamermans If I understand your question correctly. `obj = { optionalField?: string }` will be used after the validation. But in some of later usages, the ``undefined` value is not acceptable. Then for some of codes like `...(obj)`, the `optionalField: undefined` can be passed in accidently. Then I need to hard pick obj.optionalField to check if it's not `undefined`. Basically as @DarrylNoakes said, the typescript \"lies\" here in static time. I think I specifically mention the subtle difference in my question. Maybe it's not clear enough?\n- @Mike'Pomax'Kamermans I'm not sure adding that context is useful. It's just zod will bypass `undefined` with `optional()`, but in many places the `undefined` is unwelcome.\n- In terms of plain *property access*, `{}` and `{ foo: undefined }` are the same. If spread, however, `foo` would override a previously defined `foo` property if this object was spread after. The main difference I see is when using `in`/`hasOwnProperty`/`hasOwn` and such, as the property is then *present*, but has a value of `undefined`.\n- For completeness, the TS config option is `exactOptionalPropertyTypes`: \"Interpret optional property types as written, rather than adding undefined.\"\n- @Yunhai Would it be satisfactory to allow the property to be `undefined` when parsing, but have it stripped from the output? So `{ optional: undefined, other: \"str\" }` parses successfully, but the result is `{ other: \"str\" }`. I.e., is it de facto an incorrect input, or just a requirement for later code the processes the result?\n- I don't think outright disallowing is possible with Zod. It appears to read the keys specified and pass the values to the lower levels, which means the given value will always be `undefined`; i.e., there is apparently no way to tell the difference between a key being not present or it being set to `undefined`.\n- @DarrylNoakes just like what you said, it's impossible for zod to do it. There is a context behind it. I will later add my answer later based on the zod collaborator's explanation. I got an answer from them\n- This could actually be prevented with typescriptlang.org/tsconfig/#exactOptionalPropertyTypes\n- JSON.parse(JSON.stringify(result))","metadata":{"transformedAt":"2026-08-18T18:33:48.870Z","totalAnswersIncluded":0,"totalCodeBlocksIncluded":17,"totalLines":155,"estimatedTokens":1765}}75{"id":"stack-79695258","source":"stackoverflow","questionId":79695258,"title":"Zod + react-hook-form: .default(false) still resolves as boolean | undefined as if it were.optional()","tags":["reactjs","typescript","react-hook-form","zod"],"text":"Title: Zod + react-hook-form: .default(false) still resolves as boolean | undefined as if it were.optional()\nTags: reactjs, typescript, react-hook-form, zod\nSource: Stack Overflow\n\nQuestion:\nI am facing a type mismatch issue while using \"zod\" schema with `useForm` of \"react-hook-form\".\n\nResolver is showing an error for a type mismatch. I set a default value and not optional, but the error shows it has `Boolean | undefined`\nEither form hook or zodResolver is interpreting the schema and type incorrectly.\nOr I might be misunderstanding how form and zodresolver work together.\n\nDemo Code:\n\n```\nconst TestSchema = z.object({\n isFeatured: z.boolean().default(false),\n});\n\ntype TestType = z.infer;\nconst form = useForm({\n resolver: zodResolver(TestSchema),\n mode: 'onChange',\n defaultValues: {\n isFeatured: false,\n },\n});\n```\n\nError:\nIn short, it shows incompatibility between\n{ isFeatured?: boolean | undefined; }\nvs\n{ isFeatured: boolean; }\n\n```\n- Type 'Resolver' \nis not assignable to \ntype 'Resolver'.\n\n- Types of parameters 'options' and 'options' are incompatible.\n\n- Type 'ResolverOptions' \nis not assignable to \ntype 'ResolverOptions'.\n\n- Type 'boolean | undefined' \nis not assignable to \ntype 'boolean'.\n\n- Type 'undefined' is not assignable to type 'boolean'.ts(2322)\n```\n\nI wonder how it is interpreting it as\n`{ isFeatured?: boolean | undefined; }`\n\nI tried testing it with a variable of the same type:\n\n```\nconst myVar:TestType = {}\n```\n\nThis shows an error\n\n```\nProperty 'isFeatured' is missing in type '{}' but required in type '{ isFeatured: boolean; }'.ts(2741)\n```\n\nAnd added isFeatured, which removed the error.\n\n```\nlet myVar:TestType = {\n isFeatured: false,\n}\n```\n\nThis means the key isFeatured in TestType is not optional or not allowed as `undefined`.\nThen, how is resolver showing an error that it is a type of `boolean | undefined` against `boolean`?\nIs this a bug or expected behaviour for default() in the schema?\n\n========================================\n\nCode:\n```js\nconst TestSchema = z.object({\n  isFeatured: z.boolean().default(false),\n});\n\ntype TestType = z.infer<typeof TestSchema>;\nconst form = useForm<TestType>({\n  resolver: zodResolver(TestSchema),\n  mode: 'onChange',\n  defaultValues: {\n    isFeatured: false,\n  },\n});\n```\n\n```bash\n- Type 'Resolver<{ isFeatured?: boolean | undefined; }, any, { isFeatured: boolean; }>' \nis not assignable to \ntype 'Resolver<{ isFeatured: boolean; }, any, { isFeatured: boolean; }>'.\n\n- Types of parameters 'options' and 'options' are incompatible.\n\n- Type 'ResolverOptions<{ isFeatured: boolean; }>' \nis not assignable to \ntype 'ResolverOptions<{ isFeatured?: boolean | undefined; }>'.\n\n- Type 'boolean | undefined' \nis not assignable to \ntype 'boolean'.\n\n- Type 'undefined' is not assignable to type 'boolean'.ts(2322)\n```\n\n```js\nconst myVar:TestType = {}\n```\n\n```bash\nProperty 'isFeatured' is missing in type '{}' but required in type '{ isFeatured: boolean; }'.ts(2741)\n```\n\n```js\nlet myVar:TestType = {\n  isFeatured: false,\n}\n```\n\n```text\nuseForm\n```\n\n```text\nBoolean | undefined\n```\n\n```text\n{ isFeatured?: boolean | undefined; }\n```\n\n```text\nundefined\n```\n\n```text\nboolean | undefined\n```\n\n```text\nboolean\n```\n\n```js\nconst TestSchema = z.object({\n  isFeatured: z.boolean().default(false),\n});\n\ntype TestType = z.input<typeof TestSchema>, any, z.output<typeof TestSchema>; // Pass the full type signature\n\nconst form = useForm<TestType>({\n  resolver: zodResolver(TestSchema),\n  mode: 'onChange',\n  defaultValues: TestSchema.parse({}), // This extracts { isFeatured: false }\n});\n```\n\n```js\n// Result of TestSchema.parse({})\n{ isFeatured: false }\n```\n\n```text\nzodResolver\n```\n\n```text\nz.input<typeof schema>\n```\n\n```text\nz.infer<typeof schema>\n```\n\n```text\nz.output<typeof schema>\n```\n\n```text\nz.boolean().default(false)\n```\n\n```text\nz.input\n```\n\n```text\n{ isFeatured?: boolean | undefined }\n```\n\n```text\nz.output\n```\n\n```text\n{ isFeatured: boolean }\n```\n\n```text\nzodResolver\n```\n\n```text\nTestSchema.parse({})\n```\n\n========================================\n\nComments:\n- If you are setting defaultValues via React Hook Form, then you don't need the zod .default() call. Not sure if that will help\n- I don't see what you changed. `z.output` is the same as `z.infer`, and `TestSchema.parse({})` is the same as `{ isFeatured: false }`, so if the OP's code has a type error then yours would as well.\n- @Bergi You're right they're equivalent, but the it has a **TypeScript inference issue**. `useForm({resolver: zodResolver(TestSchema)})` creates competing expectations: `useForm expects {isFeatured: boolean}` but `zodResolver` uses `z.input` internally which is `{isFeatured?: boolean | undefined}`. Using `z.output` explicitly forces `TypeScript` to use output type instead of inferring from resolver's input type. `TestSchema.parse({})` ensures defaults stay synchronized with schema changes for complex schemas.\n- @darkknight Please check this link: github.com/react-hook-form/resolvers#zod it explicitly shows the zodResolver type signature for force output types // Force the output type `useForm, any, z.output>`\n- So why are you still suggesting to use `z.output` when it should be `z.input`?\n- @Bergi What did you mean it should be \"when it should be `z.input`?\" The document shows all the generic parameters that `useForm` accepts. **First parameter**: `TFieldValues` - the form field types, **Second parameter**: `TContext` - context type (usually any), **Third parameter**: `TFieldValuesOutput` - the validated output type. Do you think what doc says is **\"use z.input as your form type\"** ? but I think the docs are showing the complete type signature where `z.input` is used for internal validation.\n- @Bergi In practical standpoint, `onSubmit` handler receives the validated, complete data (with defaults applied). Form state should represent the final shape of data that we are working with. So we want type safety that matches our actual data structure. This is why we want `z.output` as our form type - it represents the data structure we'll actually be working with throughout our application.\n- It seems from your answer explanation and comments and the docs you linked that the OP should use `useForm, any, z.output>(…)`. And yet, the code in your answer after \"*The recommended approach is*\" still uses `useForm>(…)`.\n- @Bergi Of course yes, your are correct. I thought passing the `z.output` would do the job. Since it is the third parameter that `useForm` would accept we need to pass the full type signature. I will correct the answer!\n- i got one snippet which does not shows that lint error for type. const form = useForm({}) as UseFormReturn is this solution and not suppressing the error?\n- @CrackerKSR No, it is type suppression, not a solution. This forces TypeScript to trust your type claim without solving the underlying `zodResolver` input/output type mismatch. The resolver still works at runtime, but you lose type safety.","metadata":{"transformedAt":"2026-08-18T18:33:48.870Z","totalAnswersIncluded":0,"totalCodeBlocksIncluded":24,"totalLines":230,"estimatedTokens":1732}}76{"id":"stack-76537656","source":"stackoverflow","questionId":76537656,"title":"How to validate API response in RTK Query using Zod schema?","tags":["reactjs","typescript","redux-toolkit","rtk-query","zod"],"text":"Title: How to validate API response in RTK Query using Zod schema?\nTags: reactjs, typescript, redux-toolkit, rtk-query, zod\nSource: Stack Overflow\n\nQuestion:\nI want to validate the API response that I'm getting from a REST API using a Zod schema. For example, I have this user schema and this API\n\n```\nimport { z } from 'zod';\nimport { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react';\n\nconst userSchema = z.object({\n id: z.string(),\n name: z.string(),\n age: z.number(),\n});\n\ntype User = z.infer;\n\nexport const userAPI = createApi({\n reducerPath: 'userAPI',\n baseQuery: fetchBaseQuery({ baseUrl: 'https://some-api/' }),\n endpoints: (builder) => ({\n getPokemonByName: builder.query({\n query: (id) => `user/${id}`,\n }),\n }),\n})\n```\n\nI want to validate the API response against the userSchema using Zod. However, I'm unsure whether to use the parse or safeParse function provided by Zod.\n\nCould you please clarify where in my code should I perform the response validation, and whether I should use parse or safeParse for this scenario?\n\n========================================\n\nCode:\n```js\nimport { z } from 'zod';\nimport { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react';\n\n\nconst userSchema = z.object({\n  id: z.string(),\n  name: z.string(),\n  age: z.number(),\n});\n\ntype User = z.infer<typeof userSchema>;\n\n\nexport const userAPI = createApi({\n  reducerPath: 'userAPI',\n  baseQuery: fetchBaseQuery({ baseUrl: 'https://some-api/' }),\n  endpoints: (builder) => ({\n    getPokemonByName: builder.query<user, string>({\n      query: (id) => `user/${id}`,\n    }),\n  }),\n})\n```\n\n```js\nimport { z } from 'zod';\nimport { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react';\n\nconst userSchema = z.object({\n  id: z.string(),\n  name: z.string(),\n  age: z.number(),\n});\n\ntype User = z.infer<typeof userSchema>;\n\nexport const userAPI = createApi({\n  reducerPath: 'userAPI',\n  baseQuery: fetchBaseQuery({ baseUrl: 'https://some-api/' }),\n  endpoints: (build) => ({\n    getPokemonByName: builder.query({\n      query: (id) => `user/${id}`,\n      responseSchema: userSchema,\n    }),\n    getTransformedPokemonByName: build.query({\n      query: (id) => `user/${id}`,\n      // you can infer untransformed results\n      rawResponseSchema: userSchema,\n      // then infer transformed results from here\n      transformResponse: (response) => ({\n        ...response,\n        published_at: new Date(response.published_at),\n      }),\n    }),\n  }),\n})\n```\n\n```js\nimport { z } from 'zod';\nimport { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react';\n\nconst userSchema = z.object({\n  id: z.string(),\n  name: z.string(),\n  age: z.number(),\n});\n\ntype User = z.infer<typeof userSchema>;\n\nexport const userAPI = createApi({\n  reducerPath: 'userAPI',\n  baseQuery: fetchBaseQuery({ baseUrl: 'https://some-api/' }),\n  endpoints: (builder) => ({\n    getPokemonByName: builder.query<User, string>({\n      query: (id) => `user/${id}`,\n      transformResponse: (response) => {\n        userSchema.parse(response);\n        return response;\n      },\n    }),\n  }),\n});\n```\n\n```text\nresponseSchema\n```\n\n```text\nrawResponseSchema\n```\n\n```text\ntransformResponse\n```\n\n========================================\n\nComments:\n- You have `builder.query` which types the response/return value as `user`. Do you need *more* than this? What is `user` here as a type? Should you instead be using the `User` type that was inferred from the schema?\n- That just specifies what type of data you are expecting from the API, but it does not validate that the response you are getting is actually of that type. It is mostly enough if you are making the API in-house, but not if you are working with third-party APIs.\n- Thanks for your feedback and the codesandbox","metadata":{"transformedAt":"2026-08-18T18:33:48.870Z","totalAnswersIncluded":0,"totalCodeBlocksIncluded":6,"totalLines":141,"estimatedTokens":938}}77{"id":"stack-75022162","source":"stackoverflow","questionId":75022162,"title":"How to get inferred type of dynamically returned value based on passed Zod schema object?","tags":["typescript","zod"],"text":"Title: How to get inferred type of dynamically returned value based on passed Zod schema object?\nTags: typescript, zod\nSource: Stack Overflow\n\nQuestion:\nI have a function that randomly returns one of these objects:\n\n`{ name: \"Tommy\", age: 15 }`\n\n`{ car: \"BMW\" }`\n\nLet's say I want to run this function and hope that it returns me the User object instead of the Car. To verify this I want to pass it Zod schema as an argument so the function will parse it and throw an error if the random object doesn't match my schema.\n\nOtherwise, if the random object matches schema, I want to get this object returned from the function with the inferred type so I know that i have `name` and `age` properties.\n\nThat's my code:\n\n```\nimport { z } from \"zod\";\n\nconst User = z.object({\n name: z.string(),\n age: z.number()\n});\n\nconst randomObjects = [\n {\n name: \"Tommy\",\n age: 16\n },\n {\n car: \"BMW\"\n }\n];\n\nexport const getRandomObject = (\n Schema: z.AnyZodObject\n): z.infer => {\n try {\n const obj = Math.random() > 0.5 ? randomObjects[0] : randomObjects[1];\n\n Schema.parse(obj);\n\n return obj;\n } catch (error) {\n throw new Error(\"Sorry, wrong Schema passed\");\n }\n};\n\nconst user = getRandomObject(User);\nconsole.log(user);\n```\n\n`user` is being inferred as `{ [x: string]: any; }`.\n\nHow to make typescript know that it is an User object with `name` and `age` properties?\n\nCodesandbox: https://codesandbox.io/s/zod-v3g3hp?file=/src/index.ts:513-735\n\n========================================\n\nCode:\n```text\nimport { z } from \"zod\";\n\nconst User = z.object({\n  name: z.string(),\n  age: z.number()\n});\n\nconst randomObjects = [\n  {\n    name: \"Tommy\",\n    age: 16\n  },\n  {\n    car: \"BMW\"\n  }\n];\n\nexport const getRandomObject = (\n  Schema: z.AnyZodObject\n): z.infer<typeof Schema> => {\n  try {\n    const obj = Math.random() > 0.5 ? randomObjects[0] : randomObjects[1];\n\n    Schema.parse(obj);\n\n    return obj;\n  } catch (error) {\n    throw new Error(\"Sorry, wrong Schema passed\");\n  }\n};\n\nconst user = getRandomObject(User);\nconsole.log(user);\n```\n\n```text\n{ name: \"Tommy\", age: 15 }\n```\n\n```text\n{ car: \"BMW\" }\n```\n\n```text\nname\n```\n\n```text\nage\n```\n\n```text\nuser\n```\n\n```text\n{ [x: string]: any; }\n```\n\n```text\nname\n```\n\n```text\nage\n```\n\n```text\nexport const getRandomObject = <S extends z.AnyZodObject>(\n  Schema: S\n): z.infer<S> => {\n```","metadata":{"transformedAt":"2026-08-18T18:33:48.870Z","totalAnswersIncluded":0,"totalCodeBlocksIncluded":10,"totalLines":135,"estimatedTokens":578}}78{"id":"stack-69770697","source":"stackoverflow","questionId":69770697,"title":"Is there a way to have an array of objects with some of them literals?","tags":["typescript","zod"],"text":"Title: Is there a way to have an array of objects with some of them literals?\nTags: typescript, zod\nSource: Stack Overflow\n\nQuestion:\nI'm thinking about the following validation with zod and I have no clue on how to do it (or if it's possible with zod).\nI want an array of objects, all with the same shape, with some of them with literal props, I need these always present in the array.\n\nExample:\nI need always in the array the objects those with name required1 and required2, and then other objects optionals following the same shape.\n\n```\n[\n {\n name: z.literal('required1'),\n otherprop: z.number()\n },\n {\n name: z.literal('required2'),\n otherprop: z.number()\n },\n // I want to include one or more of the following too (optionals).\n {\n name: z.string(),\n otherprop: z.number()\n },\n]\n```\n\nThis other example needs to throw because required2 is missing\n\n```\n[\n {\n name: z.literal('required1'),\n otherprop: z.number()\n },\n // I want to include one or more of the following too.\n {\n name: z.string(),\n otherprop: z.number()\n },\n]\n```\n\nAny clue?\n\n========================================\n\nCode:\n```js\n[\n    {\n      name: z.literal('required1'),\n      otherprop: z.number()\n    },\n    {\n      name: z.literal('required2'),\n      otherprop: z.number()\n    },\n    // I want to include one or more of the following too (optionals).\n    {\n      name: z.string(),\n      otherprop: z.number()\n    },\n]\n```\n\n```js\n[\n    {\n      name: z.literal('required1'),\n      otherprop: z.number()\n    },\n    // I want to include one or more of the following too.\n    {\n      name: z.string(),\n      otherprop: z.number()\n    },\n]\n```\n\n```js\nconst elementSchema = z.object({\n  name: z.string(),\n  otherprop: z.number(),\n})\ntype Element = z.infer<typeof elementSchema>;\n\n// In my real code, here I have a function that returns the array of required names for the case.\nconst names = ['required1', 'required2'];\n\nfunction refineNames(elements: Element[]): boolean {\n       return names.every((el: string) => elements.some(x => x.name === el));\n}\n```\n\n```js\nz.array(elementSchema).refine(\n  (elements) => refineNames(elements),\n  { message: `There are missing names. Required names are ${names.join(', ')}`, }\n);\n```\n\n```js\nfunction hasDuplicates(elements: Element[]): boolean {\n    const names = elements.map(e => e.name);\n\n    return names.length !== new Set(names).size;\n}\n\nz.array(elementSchema).superRefine((elements, ctx) => {\n        if (refineNames(elements)) {\n            ctx.addIssue({\n                code: z.ZodIssueCode.custom,\n                message: `There are missing names. Required names are ${names.join(', ')}`,\n            });\n        }\n\n        if (hasDuplicates(elements)) {\n            ctx.addIssue({\n                code: z.ZodIssueCode.custom,\n                message: 'No duplicated name allowed.',\n            });\n        }\n    }),\n```\n\n```text\nrefine\n```\n\n```text\nrefine\n```\n\n```text\nsuperRefine\n```\n\n========================================\n\nComments:\n- @Yunnosch Thank you for the clarification and the link provided! And sorry for the inconvenience.\n- If you see my point then it was a minor effort with good effect. Have fun.","metadata":{"transformedAt":"2026-08-18T18:33:48.870Z","totalAnswersIncluded":0,"totalCodeBlocksIncluded":8,"totalLines":145,"estimatedTokens":784}}79{"id":"stack-74997333","source":"stackoverflow","questionId":74997333,"title":"Is there a Zod method that will mutate the key?","tags":["javascript","zod"],"text":"Title: Is there a Zod method that will mutate the key?\nTags: javascript, zod\nSource: Stack Overflow\n\nQuestion:\nGiven this schema, mutate the key \"user_id\" to \"user\":\n\n```\nconst schema = z.object({\n user_id: z.string() // <--- some method here to mutate the key,\n});\n\nlet input = { user_id: 1234qwer5678 }\n\nlet output = schema.parse( input )\n\nconsole.log(output) // returns { id: 1234qwer1234 }\n```\n\n========================================\n\nCode:\n```text\nconst schema = z.object({\n    user_id: z.string() // <--- some method here to mutate the key,\n});\n\nlet input = { user_id: 1234qwer5678 }\n\nlet output = schema.parse( input )\n\nconsole.log(output) // returns { id: 1234qwer1234 }\n```\n\n```js\nconst schema = z.object({\n  user_id: z.string(),\n}).transform(({ user_id, ...rest }) => ({\n  user: user_id,\n  ...rest\n});\n```\n\n```text\ntransform\n```\n\n```text\nuser_id\n```\n\n```text\nuser\n```\n\n========================================\n\nComments:\n- The wording of your question makes it slightly ambiguous which key you want: `user` or `id`. I went with the first thing you said, but the code is showing `id` in the expected output.","metadata":{"transformedAt":"2026-08-18T18:33:48.870Z","totalAnswersIncluded":0,"totalCodeBlocksIncluded":5,"totalLines":59,"estimatedTokens":280}}80{"id":"stack-76105855","source":"stackoverflow","questionId":76105855,"title":"Send blob (image) from frontend to backend with nextjs and trpc (T3 stack)","tags":["typescript","next.js","zod","trpc","t3"],"text":"Title: Send blob (image) from frontend to backend with nextjs and trpc (T3 stack)\nTags: typescript, next.js, zod, trpc, t3\nSource: Stack Overflow\n\nQuestion:\nI'm trying to send a picture of a leaflet map from the backend to the frontend where i use the **leaflet-simple-map-screenshoter** library for taking the image. This returns a blob which i want to send to the backend so I can save it into a PDF. I am using the T3 stack which uses Next.js with TRPC. I have tried numerous ways to send it, base64, plain Blob, ArrayBuffer and etc. The problem which arises is that the header request when i send it to the backend is either to large or that it just do not transfer the Blob object correctly.\n\nDo anyone have any idea on how i can solve this? Let me know if you want any other information and i will update the post as soon as possible, thanks!\n\nRegards Olav\n\n========================================\n\nTop Answer:\nAt the time of writing this, tRPC doesn't support FormData. There are some experimental methods available, but I couldn't manage to make them work.\n\n### Solution 1: Presigned URL's\n\nUpload the image directly to S3 via a presigned URL provided by a tRPC procedure. When the image has been uploaded, you can call another tRPC procedure to update any records in your database.\n\nThis has the benefit of making the upload faster and reduces the load on your Next.js server, but has the downside that you can't pre-process the image and that if there's an error you may end up with an orphan image in the s3 bucket.\n\n### Solution 2: Use Next.js 13 API routes\n\nSet up a new route in `src/app/api/` to handle file uploads. Note: Keep using tRPC for everything else in the app, and just use these endpoints to upload files.\n\nWith this alternative you can process images and have a better control of the flow, in exchange of more bandwith used.\n\nCheck out this answer where I show how I did it in my project:\n\nPOST multipart/form-data to Serverless Next.js API (running on Vercel / Now.sh)\n\n### Other solutions\n\nYou could try to use the tRPC's experimental FormData features, at your risk.\n\n========================================\n\nCode:\n```text\nFormData\n```\n\n```text\nsrc/app/api/\n```\n\n========================================\n\nComments:\n- Can I use uploadthing to upload arbitrary files? ie .onnx and other custom file types. I played around with uploading onnx before and I wasn't able to get it working. I also didn't see it in the supported file type extensions. github.com/pingdotgg/uploadthing/blob/&hellip;\n- Most recently, I set up a new t3 project (no trpc, no auth, no orm) and then copied the uploadthing docs example, to the letter, other than changed imageUploader to blobUploader github.com/currenthandle/uploadthing-test/blob/main/src/app/&zwnj;&#8203;api/&hellip; It works fine with uploading .json files but fails with .onnx files with error: Error: Could not determine type for network_single.onnx, presigned URL generation failed","metadata":{"transformedAt":"2026-08-18T18:33:48.870Z","totalAnswersIncluded":1,"totalCodeBlocksIncluded":2,"totalLines":52,"estimatedTokens":740}}81{"id":"stack-77465460","source":"stackoverflow","questionId":77465460,"title":"Zod coercion to date custom error message","tags":["typescript","date","datetime","validation","zod"],"text":"Title: Zod coercion to date custom error message\nTags: typescript, date, datetime, validation, zod\nSource: Stack Overflow\n\nQuestion:\nI have a zod schema that needs to validate a datetime from html input.\nHere's how it looks:\n\n```\nconst appointmentSchema = z.object({\n appointmentTime: z.coerce.date()\n})\n```\n\nThe problem is when I interact with the input and it is invalid, like the image below. Zod returns me the following error message: `Invalid date`.\n\nhttps://i.sstatic.net/1cgUN.png\n\nI want to customize this message but nothing seems to work, I've already tried the following:\n\n```\n...z.coerce.date({\ninvalid_type_error: 'Custom invalid date message. Doesn't work...'\n})...\n```\n\n========================================\n\nCode:\n```text\nconst appointmentSchema = z.object({\n  appointmentTime: z.coerce.date()\n})\n```\n\n```text\n...z.coerce.date({\ninvalid_type_error: 'Custom invalid date message. Doesn't work...'\n})...\n```\n\n```text\nInvalid date\n```\n\n```text\ndateOfBirth: z\n        .date({\n          errorMap: (issue, { defaultError }) => ({\n            message: issue.code === \"invalid_date\" ? \"That's not a date!\" : defaultError,\n          }),\n        })\n```\n\n========================================\n\nComments:\n- Its a bug in zod. See here for explanation and workaround: github.com/colinhacks/zod/issues/1526\n- which zod version are you using?\n- I'm using Zod ^3.22.2","metadata":{"transformedAt":"2026-08-18T18:33:48.870Z","totalAnswersIncluded":0,"totalCodeBlocksIncluded":4,"totalLines":60,"estimatedTokens":344}}82{"id":"stack-77944022","source":"stackoverflow","questionId":77944022,"title":"Custom ESLint rule to ban z.string().url() from zod","tags":["react-native","eslint","typescript-eslint","zod"],"text":"Title: Custom ESLint rule to ban z.string().url() from zod\nTags: react-native, eslint, typescript-eslint, zod\nSource: Stack Overflow\n\nQuestion:\nUnder the hood Zod's `url()` uses `new URL()` to check for validity. Sadly, the `URL` class is broken on React Native and accepts anything so I want to use other means of checking URL validity. How can I implement a `no-restricted-syntax` ESLint rule to ban `.url()` usage (using Typescript as well)?\n\nHere's a broken attempt at this:\n\n```\n'no-restricted-syntax': [\n 'error',\n {\n selector:\n \"CallExpression[callee.name='z'][callee.object.callee.property.name='string'][callee.property.name='url']\",\n message: \"Do not use z.string().url(), RN's new URL() doesn't throw on invalid URL.\",\n },\n]\n```\n\nBut this is not flagged `z.string().url()`.\n\n========================================\n\nCode:\n```js\n'no-restricted-syntax': [\n  'error',\n  {\n    selector:\n      \"CallExpression[callee.name='z'][callee.object.callee.property.name='string'][callee.property.name='url']\",\n    message: \"Do not use z.string().url(), RN's new URL() doesn't throw on invalid URL.\",\n  },\n]\n```\n\n```text\nurl()\n```\n\n```text\nnew URL()\n```\n\n```text\nURL\n```\n\n```text\nno-restricted-syntax\n```\n\n```text\n.url()\n```\n\n```text\nz.string().url()\n```\n\n```js\n'no-restricted-syntax': [\n  'error',\n  {\n    selector: \"CallExpression[callee.object.callee.object.name='z'][callee.object.callee.property.name='string'][callee.property.name='url']\",\n    message: \"Do not use z.string().url(), RN's new URL() doesn't throw on invalid URL.\"\n  }\n]\n```","metadata":{"transformedAt":"2026-08-18T18:33:48.870Z","totalAnswersIncluded":0,"totalCodeBlocksIncluded":8,"totalLines":69,"estimatedTokens":386}}83{"id":"stack-79008076","source":"stackoverflow","questionId":79008076,"title":"Type error while transforming input via Zod","tags":["typescript","zod"],"text":"Title: Type error while transforming input via Zod\nTags: typescript, zod\nSource: Stack Overflow\n\nQuestion:\nI'm trying to write a decoder function (`decode`) that takes in a Zod schema and an `unknown` input. It should be able to both validate the input and transform it if the Zod codec's input and output types are different.\n\nWhen I try to do it like this:\n\n```\nimport { ZodSchema, z } from 'zod'\n\nconst DateFromString = z.string().transform(input => new Date(input))\n\nconst Event = z.object({ timestamp: DateFromString })\n\nconst decode = (schema: ZodSchema, data: unknown): T => schema.parse(data)\n\nconst { timestamp } = decode(Event, { timestamp: '2024-01-01' })\n```\n\nI get the following type error:\n\nThe types of '_input.timestamp' are incompatible between these types.\nType 'string' is not assignable to type 'Date'.(2345)\n\nIs there a way to fix this type error **and** make sure that the `timestamp` variable at the last line is of type `Date`?\n\nAnother way to ask my question is how can I define just one `decode` function rather than repeating the implementation just for the sake of typing:\n\n```\nimport { ZodArray, ZodObject, ZodRawShape, ZodUnion, ZodUnionOptions } from 'zod'\n\nconst decodeObject = (schema: ZodObject, data: unknown) =>\n schema.parse(data)\n\nconst decodeArray = (schema: ZodArray>, data: unknown) =>\n schema.parse(data)\n\nconst decodeUnion = (schema: ZodUnion, data: unknown) =>\n schema.parse(data)\n```\n\n========================================\n\nCode:\n```text\nimport { ZodSchema, z } from 'zod'\n\nconst DateFromString = z.string().transform(input => new Date(input))\n\nconst Event = z.object({ timestamp: DateFromString })\n\nconst decode = <T>(schema: ZodSchema<T>, data: unknown): T => schema.parse(data)\n\nconst { timestamp } = decode(Event, { timestamp: '2024-01-01' })\n```\n\n```text\nimport { ZodArray, ZodObject, ZodRawShape, ZodUnion, ZodUnionOptions } from 'zod'\n\nconst decodeObject = <T extends ZodRawShape>(schema: ZodObject<T>, data: unknown) =>\n  schema.parse(data)\n\nconst decodeArray = <T extends ZodRawShape>(schema: ZodArray<ZodObject<T>>, data: unknown) =>\n  schema.parse(data)\n\nconst decodeUnion = <T extends ZodUnionOptions>(schema: ZodUnion<T>, data: unknown) =>\n  schema.parse(data)\n```\n\n```text\ndecode\n```\n\n```text\nunknown\n```\n\n```text\ntimestamp\n```\n\n```text\nDate\n```\n\n```text\ndecode\n```\n\n```text\nfunction decode<T extends z.ZodTypeAny>(schema: T, data: unknown) {\n    return schema.parse(data) as z.infer<T>;\n}\n```\n\n```text\n// With 'custom' we need to provide our own validation\nconst DateType = z.custom<Date>(\n    (input) => new Date(input).toString() !== 'Invalid Date'\n); // Weak validation\n\nconst DateFromString = z\n    .string() // validate string\n    .transform((v) => new Date(v)) // transform to Date\n    .pipe(DateType); // validate Date\n```\n\n```text\nconst DateFromString = z.string().date();\n```\n\n```text\nDate\n```\n\n```text\nzod.custom\n```\n\n========================================\n\nComments:\n- Many thanks, your version of the `decode` function did the trick for me even without having to change my original version of `DateFromString`.\n- You just made me realize that the problem is the decode fn. I will fix the answer.","metadata":{"transformedAt":"2026-08-18T18:33:48.870Z","totalAnswersIncluded":0,"totalCodeBlocksIncluded":12,"totalLines":126,"estimatedTokens":793}}84{"id":"stack-77461140","source":"stackoverflow","questionId":77461140,"title":"How to define the type for a nullish value with schema from Zod","tags":["javascript","typescript","zod"],"text":"Title: How to define the type for a nullish value with schema from Zod\nTags: javascript, typescript, zod\nSource: Stack Overflow\n\nQuestion:\nI have a type defined with zod.\n\nAm inexperienced with TypeScript.\n\nThe zod object looks like this:\n\n```\nimport z from 'zod';\nconst clientSchema = z.object({\n name: z.string(),\n details: z.object({\n detail1: z.string().optional()\n }\n }\n);\nexport type ClientSchema = z.infer;\n```\n\nAssigning the `details` of a `client` of type `ClientSchema`, I was hoping\nto be able to annotate it's type like this:\n\n```\nconst details = {\n detail1: ''\n}\n```\n\nBut TypeScript complains:\n\nTypes of property 'detail1' are incompatible.\nType 'string | undefined' is not assignable to type 'string'.\nType 'undefined' is not assignable to type 'string'.\"\n\nSo now I have created a separate Schema for details:\n\n```\nexport const detailSchema = z.object({\n detail1: z.string().optional() ,\n});\nexport type DetailSchema = z.infer;\n```\n\nAnd then declare the object:\n\n```\nconst details: DetailSchema = {\n detail1: 'a string'\n}\n```\n\nIs that the expected/recommended approach for sub-objects?\n\n========================================\n\nCode:\n```text\nimport z from 'zod';\nconst clientSchema = z.object({\n  name: z.string(),\n  details: z.object({\n    detail1: z.string().optional()\n    }\n  }\n);\nexport type ClientSchema = z.infer<typeof clientSchema>;\n```\n\n```text\nconst details = {\n  detail1: <string|null|undefined> ''\n}\n```\n\n```text\nexport const detailSchema = z.object({\n    detail1: z.string().optional() ,\n});\nexport type DetailSchema = z.infer<typeof detailSchema>;\n```\n\n```text\nconst details: DetailSchema = {\n  detail1: 'a string'\n}\n```\n\n```text\ndetails\n```\n\n```text\nclient\n```\n\n```text\nClientSchema\n```\n\n```text\nconst clientSchema = z.object({\n  name: z.string(),\n  details: z.object({\n    detail1: z.string().nullable().optional()\n  })\n});\n```\n\n```text\ntype ClientSchema = {\n    name: string;\n    details: {\n        detail1?: string | null | undefined;\n    };\n}\n```\n\n```text\ntype DetailSchema = {\n    detail1?: string | null | undefined;\n}\n```\n\n```text\nconst details: DetailsSchema = {\n  details1: \"\"  // string | null | undefined\n}\n```\n\n```text\nnullable\n```\n\n```text\nnull\n```\n\n```text\nundefined\n```\n\n```text\nproperty: z.string().nullable().optional()\n```\n\n```text\ndetails\n```\n\n```text\ntype DetailSchema = ClientSchema[\"details\"];\n```","metadata":{"transformedAt":"2026-08-18T18:33:48.870Z","totalAnswersIncluded":0,"totalCodeBlocksIncluded":17,"totalLines":156,"estimatedTokens":588}}85{"id":"stack-79435905","source":"stackoverflow","questionId":79435905,"title":"Coerce string to literal number with Zod","tags":["typescript","validation","zod"],"text":"Title: Coerce string to literal number with Zod\nTags: typescript, validation, zod\nSource: Stack Overflow\n\nQuestion:\nI have a property that is supposed to allow only certain numbers:\n\n```\n{\n ...\n x: 1 | -1\n}\n```\n\nHow to define this in the input validation schema?\n\nIf input is JSON it's easy:\n\n```\nx: z.union([z.literal(-1), z.literal(1)])\n```\n\nbut if input comes in the search query, then values are strings, so I need to be able to coerce to number, but still limit to -1 and 1 to make the inferred type from the schema compatible with the TypeScript type.\n\n========================================\n\nCode:\n```text\n{\n   ...\n   x: 1 | -1\n}\n```\n\n```text\nx: z.union([z.literal(-1), z.literal(1)])\n```\n\n```text\n// union of\nz.union([\n  z.number(), // number or\n  z.string().transform(str => parseInt(str, 10)) // string transformed to number\n]).refine(v => [1,-1].includes(v)); // refined to allow a set of numbers\n```\n\n```text\n// union of\nz.union([\n  z.number(), // number or\n  z.string().transform(str => parseInt(str, 10)) // string transformed to number\n]).pipe(z.union([z.literal(1), z.literal(-1)]))\n```\n\n```text\nz.preprocess(\n    v => typeof v === 'number' ? v : parseInt(v, 10), // preprocessing\n    z.number() // as number\n).pipe(z.union([z.literal(1), z.literal(-1)]));\n```\n\n```text\n// coerce internally uses Number(value)\nz.coerce.number().pipe(z.union([z.literal(1), z.literal(-1)]));\n```\n\n========================================\n\nComments:\n- I noticed it can be done directly from transform, `z.coerce.number().transform(v => v > 0 ? 1 : -1)`. without any pipe","metadata":{"transformedAt":"2026-08-18T18:33:48.870Z","totalAnswersIncluded":0,"totalCodeBlocksIncluded":6,"totalLines":70,"estimatedTokens":393}}86{"id":"stack-75063559","source":"stackoverflow","questionId":75063559,"title":"Custom Zod errors in tRPC","tags":["zod","trpc.io"],"text":"Title: Custom Zod errors in tRPC\nTags: zod, trpc.io\nSource: Stack Overflow\n\nQuestion:\nHow can I set up tRPC so that when zod throws an error I can handle it instead of tRPC. I have looked everywhere for an answer and I can't find one\n\n========================================\n\nTop Answer:\nhttps://trpc.io/docs/error-handling#handling-errors\n\nAll errors that occur in a procedure go through the onError method before being sent to the client. Here you can handle or change errors.\n\nHere's a basic example of changing a zod error on server, before it hits client:\n\n```\nonError: ({ error }) => {\n if (error.cause instanceof ZodError) {\n // Returning only first zod error message to client\n error.message = JSON.parse(error.message)[0].message;\n }\n}\n```\n\n========================================\n\nCode:\n```js\n// backend/src/trpc/types.ts\n\nimport { typeToFlattenedError } from \"zod\";\nimport type { RuntimeConfig } from '@trpc/server/src/core/internals/config';\nimport { TRPC_ERROR_CODE_NUMBER } from '@trpc/server/src/rpc';\nimport { TRPCErrorShape } from '@trpc/server/src/rpc/envelopes';\n\n// Utility type to replace the return type of a function\nexport type ReplaceReturnType<T extends (...a: any) => any, TNewReturn> = (...a: Parameters<T>) => TNewReturn;\n\n// Flattened zod error\nexport type FlattenedZodError = typeToFlattenedError<any, string>\n\n// This obscure type is taken from TrpcErrorShape, and extends the data property with \"inputValidationError\"\nexport type CustomErrorShape = TRPCErrorShape<\n  TRPC_ERROR_CODE_NUMBER,\n  Record<string, unknown> & { inputValidationError: FlattenedZodError | null }\n>\n\n// This type extends the errorFormatter property with the custom error shape\nexport type CustomErrorFormatter = ReplaceReturnType<RuntimeConfig<any>['errorFormatter'], CustomErrorShape>;\n```\n\n```js\n// backend/src/trpc/errorFormatter.ts\n\nimport { ZodError, } from 'zod';\nimport { CustomErrorFormatter } from './types';\n\nexport const errorFormatter: CustomErrorFormatter = (opts) => {\n  const { shape, error } = opts;\n\n  const isInputValidationError = error.code === \"BAD_REQUEST\" && error.cause instanceof ZodError\n\n  if (isInputValidationError) {\n    console.log(error.cause.flatten());\n  }\n\n  return {\n    ...shape,\n    data: {\n      ...shape.data,\n      inputValidationError: isInputValidationError ? error.cause.flatten() : null\n    }\n  }\n}\n```\n\n```js\n// backend/src/trpc/instance.trpc\n\nimport { initTRPC } from \"@trpc/server\";\nimport { errorFormatter } from \"./errorFormatter\";\n\nconst t = initTRPC.create({\n  errorFormatter\n});\n\n// router\nexport const router = t.router;\nexport const publicProcedure = t.procedure;\n```\n\n```html\n<script lang=\"ts\">\n    // frontend/src/lib/auth/LoginForm.svelte\n    import type { FlattenedZodError } from 'backend/src/trpc/types';\n    import { trpcClient as t } from '$lib/trpc';\n\n    let email: string = '';\n    let password: string = '';\n\n    let _formErrors: FlattenedZodError['formErrors'];\n    let _fieldErrors: FlattenedZodError['fieldErrors'];\n\n    const doLogin = async () => {\n        try {\n            const result = await t.user.login.mutate({\n                email,\n                password\n            });\n\n            if (result.token) {\n                localStorage.setItem('token', result.token);\n                window.location.href = '/';\n            }\n        } catch (e: any) {\n            if (e.data && e.data.inputValidationError != null) {\n                // here is where we get the errors\n                const { fieldErrors, formErrors } = e.data.inputValidationError as FlattenedZodError;\n                _fieldErrors = fieldErrors;\n                _formErrors = formErrors;\n            } else {\n                console.log('Unknown error', e);\n            }\n        }\n    };\n</script>\n\n<div class=\"card bg-base-200\">\n    <div class=\"card-body\">\n        <div class=\"card-title\">\n            <h1 class=\"header-2\">Login</h1>\n        </div>\n        {#if _formErrors?.length > 0}\n            <div class=\"alert alert-error flex flex-col gap-2\">\n                {#each _formErrors as error}\n                    <p>{error}</p>\n                {/each}\n            </div>\n        {/if}\n        <form on:submit={doLogin} class=\"flex flex-col gap-4\">\n            <div>\n                <input\n                    class={'input input-bordered input-ghost ' + (_fieldErrors?.email ? 'input-error' : '')}\n                    type=\"email\"\n                    placeholder=\"Email\"\n                    bind:value={email}\n                />\n                {#if _fieldErrors?.email}\n                    <div class=\"text-error flex flex-col gap-0\">\n                        {#each _fieldErrors.email as error}\n                            <p>{error}</p>\n                        {/each}\n                    </div>\n                {/if}\n            </div>\n            <div>\n                <input\n                    class={'input input-bordered input-ghost ' +\n                        (_fieldErrors?.password ? 'input-error' : '')}\n                    type=\"password\"\n                    placeholder=\"Password\"\n                    bind:value={password}\n                />\n                {#if _fieldErrors?.password}\n                    <div class=\"text-error flex flex-col gap-2\">\n                        {#each _fieldErrors.password as error}\n                            <p>{error}</p>\n                        {/each}\n                    </div>\n                {/if}\n            </div>\n            <input type=\"submit\" class=\"btn btn-primary\" value=\"Submit\" />\n        </form>\n    </div>\n</div>\n```\n\n```text\nonError\n```\n\n```text\nonError\n```\n\n```text\nflatten()\n```\n\n```js\nonError: ({ error }) => {\n    if (error.cause instanceof ZodError) {\n        // Returning only first zod error message to client\n        error.message = JSON.parse(error.message)[0].message;\n    }\n}\n```\n\n========================================\n\nComments:\n- Could you post some code or examples of things you have tried?\n- Ah, such a comprehensive response, TIL Zod errors can be flattened – thank you! <3","metadata":{"transformedAt":"2026-08-18T18:33:48.870Z","totalAnswersIncluded":1,"totalCodeBlocksIncluded":8,"totalLines":204,"estimatedTokens":1506}}87{"id":"stack-77457873","source":"stackoverflow","questionId":77457873,"title":"Zod validation does not seem to trigger for required input","tags":["reactjs","typescript","zod"],"text":"Title: Zod validation does not seem to trigger for required input\nTags: reactjs, typescript, zod\nSource: Stack Overflow\n\nQuestion:\nI have the following schema in Zod that requires a valid string input. However, I'm not sure the validation is actually kicking in? Just wondering what I'm doing wrong...\n\n```\nconst nameSchema = z.string({\n required_error: \"Name is required\",\n invalid_type_error: \"Name must be a string\",\n }); \n\n console.log(nameSchema.safeParse(\"\")); //Return the following object\n\n{\n \"success\": true,\n \"data\": \"\"\n}\n```\n\n========================================\n\nCode:\n```text\nconst nameSchema = z.string({\n    required_error: \"Name is required\",\n    invalid_type_error: \"Name must be a string\",\n  });  \n\n  console.log(nameSchema.safeParse(\"\")); //Return the following object\n\n{\n    \"success\": true,\n    \"data\": \"\"\n}\n```\n\n```text\nconst nameSchema = z.string({\n  required_error: \"Name is required\",\n  invalid_type_error: \"Name must be a string\",\n}).refine(data => data.trim() !== \"\", {\n  message: \"Name cannot be an empty string\",\n});\n\nconsole.log(nameSchema.safeParse(\"\"));\n```","metadata":{"transformedAt":"2026-08-18T18:33:48.870Z","totalAnswersIncluded":0,"totalCodeBlocksIncluded":2,"totalLines":48,"estimatedTokens":274}}88{"id":"stack-73985439","source":"stackoverflow","questionId":73985439,"title":"Make Zod parse if available, and if not skip element","tags":["typescript","zod"],"text":"Title: Make Zod parse if available, and if not skip element\nTags: typescript, zod\nSource: Stack Overflow\n\nQuestion:\nI've searched through the documentation but find no solution for this case. I've got the following schemas.\n\n```\nconst RelationSchema = z.object({\n guid: z.string(),\n createdDate: z.preprocess(castToDate, z.date()),\n modifiedDate: z.preprocess(castToDate, z.date()).nullable(),\n name: z.string(),\n publicationtype: z.string(),\n contentType: z.string(),\n});\nexport const NobbRelationsSchema = z.array(NobbRelationSchema);\n```\n\nWhen parsing an array with `NobbRelationsSchema.parse()` I sometimes get back `name` as undefined. In these cases I would like Zod not to throw an error, but instead just remove that element and continue with the rest. A kind of filtering.\n\nThe option I see is to use `safeParse` and set `name` as optional and filter out these afterwards. However, it messes up the TypeScript type checking later in code, as `name` should always be set for valid elements.\n\n========================================\n\nCode:\n```text\nconst RelationSchema = z.object({\n    guid: z.string(),\n    createdDate: z.preprocess(castToDate, z.date()),\n    modifiedDate: z.preprocess(castToDate, z.date()).nullable(),\n    name: z.string(),\n    publicationtype: z.string(),\n    contentType: z.string(),\n});\nexport const NobbRelationsSchema = z.array(NobbRelationSchema);\n```\n\n```text\nNobbRelationsSchema.parse()\n```\n\n```text\nname\n```\n\n```text\nsafeParse\n```\n\n```text\nname\n```\n\n```text\nname\n```\n\n```js\nimport { z } from 'zod';\n// -- snip your code here --\ntype NobbRelation = z.TypeOf<typeof RelationSchema>;\n\nfunction parseData(data: unknown) {\n  // First parse the shape of the array separately from the elements.\n  const dataArr = z.array(z.unknown()).parse(data);\n\n  // Next parse each element individually and return a sentinal value\n  // to filter out. In this case I used `null`.\n  return dataArr\n    .map(datum => {\n      const parsed = RelationSchema.safeParse(datum);\n      return parsed.success ? parsed.data : null;\n    })\n    // If the filter predicate is a type guard, the types will be correct\n    .filter((x: NobbRelation | null): x is NobbRelation => x !== null);\n}\n```\n\n```js\ntype NobbRelations = NobbRelation[]; // Or just write this inline\n```\n\n```text\nsafeParse\n```\n\n```text\nz.array\n```\n\n```text\narray\n```\n\n```text\ntransform\n```\n\n```text\nfilter\n```\n\n```text\nNobbRelationsSchema\n```","metadata":{"transformedAt":"2026-08-18T18:33:48.870Z","totalAnswersIncluded":0,"totalCodeBlocksIncluded":14,"totalLines":106,"estimatedTokens":603}}89{"id":"stack-73413992","source":"stackoverflow","questionId":73413992,"title":"How to use parameter as type definition?","tags":["typescript","zod"],"text":"Title: How to use parameter as type definition?\nTags: typescript, zod\nSource: Stack Overflow\n\nQuestion:\nIs it possible to dynamically define a parameter type based on another parameter?\n\nLike in the following scenario:\n\n```\nimport z from 'zod'\n\n// I have a function that defines a command factory with a build function\nconst defineCommand = (name:string, schema: z.ZodTypeAny) => {\n return {\n schema,\n build: (payload: z.infer) => {\n return {\n payload\n }\n }\n }\n}\n\nconst CreatePostCommand = defineCommand('CreatePostCommand', z.object({\n title: z.string().min(2),\n body: z.string().min(2)\n}));\n\n// now when I call the build function there is no type check for the payload\nconst commandInstance = CreatePostCommand.build({foo: \"bar\"}) // I know that it works with generics but this way I would have to pass in the \"schema\" twice. Once as type and once as schema object.\n\n========================================\n\nCode:\n```js\nimport z from 'zod'\n\n// I have a function that defines a command factory with a build function\nconst defineCommand = (name:string, schema: z.ZodTypeAny) => {\n    return {\n        schema,\n        build: (payload: z.infer<typeof schema>) => {\n            return {\n                payload\n            }\n        }\n    }\n}\n\nconst CreatePostCommand = defineCommand('CreatePostCommand', z.object({\n    title: z.string().min(2),\n    body: z.string().min(2)\n}));\n\n// now when I call the build function there is no type check for the payload\nconst commandInstance = CreatePostCommand.build({foo: \"bar\"}) // <<-- this should cause type error\n```\n\n```js\nconst defineCommand = <T extends z.ZodType>(name:string, schema: T) => {\n    return {\n        schema,\n        build: (payload: z.infer<T>) => {\n            return {\n                payload\n            }\n        }\n    }\n}\n```\n\n========================================\n\nComments:\n- thanks, that works. I didn't know that it also works the other way around!","metadata":{"transformedAt":"2026-08-18T18:33:48.870Z","totalAnswersIncluded":0,"totalCodeBlocksIncluded":2,"totalLines":76,"estimatedTokens":480}}90{"id":"stack-79759518","source":"stackoverflow","questionId":79759518,"title":"\"TypeError: Cannot read properties of undefined (reading 'traits')\" When using Zod to validate incoming data","tags":["typescript","next.js","zod"],"text":"Title: \"TypeError: Cannot read properties of undefined (reading 'traits')\" When using Zod to validate incoming data\nTags: typescript, next.js, zod\nSource: Stack Overflow\n\nQuestion:\nI'm currently trying to validate a JSON object coming from a database into my web app, and I keep getting the error message: `TypeError: Cannot read properties of undefined (reading 'traits')`. There are no properties named \"traits\" in my Zod schema or in the JSON object that I am validating, so IDK how this could be happening.\n\nZod Schema:\n\n```\nconst Image = z.object({\n type: z.literal([\"profile\", \"banner\"]),\n url: z.string(),\n width: z.number(),\n height: z.number(),\n})\n\nconst Tournament = z.object({\n id: z.number(),\n name: z.string(),\n slug: z.string(),\n startAt: z.number(),\n images: z.array(Image),\n city: z.nullable(z.string()),\n addrState: z.nullable(z.string()),\n countryCode: z.nullable(z.string()),\n isOnline: z.boolean,\n venueAddress: z.nullable(z.string()),\n mapsPlaceId: z.nullable(z.string())\n})\n\nconst StartggResponse = z.object({\n pageInfo: z.object({\n totalPages: z.number()\n }),\n nodes: z.array(Tournament)\n})\n```\n\nJSON Object:\n\n```\n{\n \"nodes\": [{\n \"addrState\": null,\n \"city\": null,\n \"countryCode\": null,\n \"id\": 823671,\n \"images\": [\n {\"type\": \"profile\", \"url\": \"https://images.start.gg/images/tournament/823671/image-5b201a410655f865d59a9cbd7b0e5635.png\", \"width\": 2048, \"height\": 2048},\n {\"type\": \"banner\", \"url\": \"https://images.start.gg/images/tournament/823671/image-fc95fcf9a89b8eb8f3a309113335bcdf.png\", \"width\": 1947, \"height\": 902}\n ],\n \"isOnline\": true,\n \"mapsPlaceId\": null,\n \"name\": \"GACKED\",\n \"slug\": \"tournament/gacked\",\n \"startAt\": 1757406600,\n \"venueAddress\": \"\"\n }],\n\n \"pageInfo\": {\n \"totalPages\": 143\n }\n}\n```\n\n========================================\n\nTop Answer:\nThe issue with your code is that you are not properly using `.literal` over here. `.literal` only takes one value in your case you should write it with an enum like this: `type: z.enum([\"profile\", \"banner\"])` also for the `z.boolean` that's also a wrong way of writing it simply writing `isOnline: boolean` is the correct way.\n\n========================================\n\nCode:\n```js\nconst Image = z.object({\n    type: z.literal([\"profile\", \"banner\"]),\n    url: z.string(),\n    width: z.number(),\n    height: z.number(),\n})\n\nconst Tournament = z.object({\n    id: z.number(),\n    name: z.string(),\n    slug: z.string(),\n    startAt: z.number(),\n    images: z.array(Image),\n    city: z.nullable(z.string()),\n    addrState: z.nullable(z.string()),\n    countryCode: z.nullable(z.string()),\n    isOnline: z.boolean,\n    venueAddress: z.nullable(z.string()),\n    mapsPlaceId: z.nullable(z.string())\n})\n\nconst StartggResponse = z.object({\n    pageInfo: z.object({\n        totalPages: z.number()\n    }),\n    nodes: z.array(Tournament)\n})\n```\n\n```json\n{\n  \"nodes\": [{\n    \"addrState\": null,\n    \"city\": null,\n    \"countryCode\": null,\n    \"id\": 823671,\n    \"images\": [\n      {\"type\": \"profile\", \"url\": \"https://images.start.gg/images/tournament/823671/image-5b201a410655f865d59a9cbd7b0e5635.png\", \"width\": 2048, \"height\": 2048},\n      {\"type\": \"banner\", \"url\": \"https://images.start.gg/images/tournament/823671/image-fc95fcf9a89b8eb8f3a309113335bcdf.png\", \"width\": 1947, \"height\": 902}\n    ],\n    \"isOnline\": true,\n    \"mapsPlaceId\": null,\n    \"name\": \"GACKED\",\n    \"slug\": \"tournament/gacked\",\n    \"startAt\": 1757406600,\n    \"venueAddress\": \"\"\n  }],\n\n  \"pageInfo\": {\n    \"totalPages\": 143\n  }\n}\n```\n\n```text\nTypeError: Cannot read properties of undefined (reading 'traits')\n```\n\n```ts\nisOnline: z.boolean(),\n```\n\n```text\nz.boolean\n```\n\n```text\nisOnline\n```\n\n```text\nTournament\n```\n\n```text\n.literal\n```\n\n```text\n.literal\n```\n\n```text\ntype: z.enum([\"profile\", \"banner\"])\n```\n\n```text\nz.boolean\n```\n\n```text\nisOnline: boolean\n```\n\n========================================\n\nComments:\n- Please the code you use to parse the data with the schema\n- Here's a reproduction. Feel free to fork that and edit it into your question.\n- The full error message I see is `TypeError: can't access property \"traits\", def.shape[k]._zod is undefined` (you could also edit this into your question). It's coming from the `normalizeDef` function in zod itself (the full expression is `def.shape[k]._zod.traits.has(\"$ZodType\")`), so it's unsurprising that `traits` doesn't appear in your code.\n- \"`.literal` only takes one value\"—`.literal` can take an array of literals and in that case it returns validator for a union type. This is mentioned in the docs (look for \"To allow multiple literal values\") and can be seen in the type signature.\n- It's unfortunate that Zod allows you to create a broken validator in the first place. Feels to me like `z.object` ought to be typed such that `z.object({ a: z.boolean })` is rejected by TypeScript, or at least `z.object`'s implementation should eagerly validate its parameter and immediately throw if you pass it something invalid. I don't personally use Zod and don't know if there's some reason why this would be infeasible, but if you agree with me you could consider filing an issue.\n- Damn I should've checked harder. Thanks man!\n- I had a similar issue with enums, where I just wrote the `movmentType: movTypes` (the enum name), instead of `movementType: z.enum(movTypes)`.","metadata":{"transformedAt":"2026-08-18T18:33:48.870Z","totalAnswersIncluded":1,"totalCodeBlocksIncluded":12,"totalLines":179,"estimatedTokens":1319}}91{"id":"stack-79839390","source":"stackoverflow","questionId":79839390,"title":"Zod email validation issue","tags":["reactjs","react-hook-form","zod"],"text":"Title: Zod email validation issue\nTags: reactjs, react-hook-form, zod\nSource: Stack Overflow\n\nQuestion:\n### Issue\n\nI'm working on a React application and wanted to try the newest version of Zod (`4.1.13`) for input validations along with react hook form. I've been struggling with the `z.email()` function as it's not displaying the correct message when the user tries to submit the form with no values at all. Instead, the message I always get is the 'Invalid email...' message for that field.\n\nThe Zod's documentation (which is not that informative about it) says that you should use the new `error` property and validate if the input is undefined. i.e.\n\n```\nconst LoginSchema = z.object({\n email: z.email({\n error: (issue) =>\n issue.input === undefined\n ? 'Email field is required'\n : 'Invalid email format',\n }),\n```\n\nI tried that but it's still failing, I have no clue about what could be the issue, I tried numerous options to display custom messages, like using the `min` property, or even use the `string` function before the email one, but is not allowed to do so in this version. I've heard that some other people may have had the same problem, but couldn't find any useful solution yet.\n\n### Attempts to fix the issue:\n\n- I tried chaining `.string()` before `.email()`, but Zod `v4` doesn't seem to allow this sequence.\n\n========================================\n\nTop Answer:\nI also encountered the same issue. You can better add regex rather than using the depreciated method. For example, I just something like below for my code.\n\n```\nemail: z\n .string()\n .refine((val) => /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(val), \"Invalid Email\")\n .toLowerCase()\n```\n\n========================================\n\nCode:\n```jsx\nconst LoginSchema = z.object({\n  email: z.email({\n    error: (issue) =>\n      issue.input === undefined\n        ? 'Email field is required'\n        : 'Invalid email format',\n  }),\n```\n\n```text\n4.1.13\n```\n\n```text\nz.email()\n```\n\n```text\nerror\n```\n\n```text\nmin\n```\n\n```text\nstring\n```\n\n```text\n.string()\n```\n\n```text\n.email()\n```\n\n```text\nv4\n```\n\n```js\nconst LoginSchema = z.object({\n  email: z.email({\n    error: (issue) =>\n      issue.input === undefined\n        ? 'Email field is required'\n        : 'Invalid email format',\n  })\n})\n```\n\n```js\nconst LoginSchema = z.object({\n  email: z.email({\n    error: (issue) =>\n      issue.input === \"\" ? \"Email field is required\" : \"Invalid email format\",\n  }),\n});\n```\n\n```js\nconst LoginSchema = z.object({\n  email: z.email({\n    error: (issue) =>\n      !issue.input ? \"Email field is required\" : \"Invalid email format\",\n  }),\n});\n```\n\n```text\nLoginSchema.parse({ email: undefined })\n```\n\n```text\n\"Email field is required\"\n```\n\n```text\nissue.value\n```\n\n```js\nemail: z\n      .string()\n      .refine((val) => /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(val), \"Invalid Email\")\n      .toLowerCase()\n```\n\n========================================\n\nComments:\n- So what exactly is the `issue.input` in that `error` callback? What object are you trying to parse with the schema?\n- I previously tried that as well; it didn't work the first time. But checking your solution, I remembered that the browser also applies some validations by itself when you use the email input type. I just added the `noValidate` attribute to the form, and it works now. Thank you for your help!\n- @AndresGomez I had a similar problem with `type=\"email`, it did not show any error messages. I changed it to `type=\"text\"` first, but now I may try `formNoValidate` to the input or `noValidate` on the whole form which is even better as the whole validation is handled by zod.","metadata":{"transformedAt":"2026-08-18T18:33:48.871Z","totalAnswersIncluded":1,"totalCodeBlocksIncluded":16,"totalLines":138,"estimatedTokens":898}}92{"id":"stack-78571886","source":"stackoverflow","questionId":78571886,"title":"FormMessage not displaying zod validation error - Shadcn, Zod, react-hook-form, Next.js","tags":["next.js","react-hook-form","zod","shadcnui"],"text":"Title: FormMessage not displaying zod validation error - Shadcn, Zod, react-hook-form, Next.js\nTags: next.js, react-hook-form, zod, shadcnui\nSource: Stack Overflow\n\nQuestion:\nI have some troubles with zod validation error displaying in the FormMessage. I've been following the shadcn documentation on form and input and I've done everything the same, but I can't seem to figure it out why this is not working.\n\nI have this form-input component (did it so that it can be reused)\n\n```\nexport const FormInput = (\n props: FormElementProps\n) => {\n return (\n (\n \n {props.label && {props.label}}\n\n \n \n \n\n {props.description && (\n {props.description}\n )}\n\n \n \n )}\n />\n );\n};\n```\n\nThe zod schema is the following\n\n```\nexport const loginViewFormSchema = z.object({\n email: z.string().email({ message: \"Email is required\" }),\n password: z.string().min(1, {\n message: \"Password is required\",\n }),\n});\nconst loginForm = useForm>({\n resolver: zodResolver(loginViewFormSchema),\n defaultValues: {\n email: \"\",\n password: \"\",\n },\n });\n```\n\nAnd the form is used like this\n\n```\n\n \n \n\n \n\n \n {formState.isSubmitting && (\n \n )}\n Sign In\n \n\n \nHaving trouble signing in?\n \n \n \n```\n\nThere should be validation errors displayed under each input if the values are not as they should be based on the zod schema, but nothing happens\nhttps://i.sstatic.net/kEnaU4Db.png\n\nHere is a link to a code sandbox which reproduces the problems\nhttps://codesandbox.io/p/devbox/sharp-jasper-z6c4gz?file=%2Fapp%2Fpage.tsx%3A15%2C6\n\nI tried reinstalling the react-hook-form and zod packages and downgrading, but nothing worked. I've seen that the form errors are as expected per the schema definition, but the error message is not passed to the FormMessage from the FormInput component.\n\n========================================\n\nTop Answer:\nyou dont use this properly:\n\n```\nconst loginForm = useForm>({\n resolver: zodResolver(loginViewFormSchema),\n defaultValues: {\n email: \"\",\n password: \"\",\n },\n });\n```\n\nyou are passing `loginForm` to each `FormInput` component as `props`. this also has `errors` property. in your `FormInput` component:\n\n```\nexport const FormInput = (\n props: FormElementProps,\n) => {\n return (\n (\n \n {props.label && {props.label}}\n\n \n \n \n\n {props.description && (\n {props.description}\n )}\n\n \n \n )}\n />\n );\n}; \nFormInput.displayName = \"FormInput\";\n```\n\nyou should add this to `FormInput`\n\n```\n{props.error && {error.message}}\n```\n\n========================================\n\nCode:\n```text\nexport const FormInput = <T extends FieldValues>(\n  props: FormElementProps<T>\n) => {\n  return (\n    <FormField\n      control={props.form.control}\n      name={props.name}\n      render={({ field }) => (\n        <FormItem>\n          {props.label && <FormLabel>{props.label}</FormLabel>}\n\n          <FormControl>\n            <Input\n              {...field}\n              type={props.type}\n              disabled={props.disabled}\n              placeholder={props.placeholder}\n            />\n          </FormControl>\n\n          {props.description && (\n            <FormDescription>{props.description}</FormDescription>\n          )}\n\n          <FormMessage />\n        </FormItem>\n      )}\n    />\n  );\n};\n```\n\n```text\nexport const loginViewFormSchema = z.object({\n  email: z.string().email({ message: \"Email is required\" }),\n  password: z.string().min(1, {\n    message: \"Password is required\",\n  }),\n});\nconst loginForm = useForm<z.infer<typeof loginViewFormSchema>>({\n    resolver: zodResolver(loginViewFormSchema),\n    defaultValues: {\n      email: \"\",\n      password: \"\",\n    },\n  });\n```\n\n```text\n<Form {...props.form}>\n        <form\n          onSubmit={handleSubmit(formSubmitHandler)}\n          className=\"flex flex-col space-y-2\"\n        >\n          <FormInput\n            form={props.form}\n            label=\"Email\"\n            name=\"email\"\n            disabled={formState.isSubmitting}\n          />\n\n          <FormInput\n            form={props.form}\n            label=\"Password\"\n            name=\"password\"\n            type=\"password\"\n            disabled={formState.isSubmitting}\n          />\n\n          <Button type=\"submit\" disabled={formState.isSubmitting}>\n            {formState.isSubmitting && (\n              <Icons.spinner className=\"w-4 h-4 mr-2 animate-spin\" />\n            )}\n            Sign In\n          </Button>\n\n          <Button type=\"button\" variant=\"link\" onClick={onClickForgotPassword}>\nHaving trouble signing in?\n          </Button>\n        </form>\n      </Form>\n```\n\n```js\nform={{\n        ...loginForm,\n        formState: {\n          ...loginForm.formState,\n          isSubmitting: loginForm.formState.isSubmitting,\n        },\n      }}\n```\n\n```js\nform={loginForm}\n```\n\n```text\nconst loginForm = useForm<z.infer<typeof loginViewFormSchema>>({\n    resolver: zodResolver(loginViewFormSchema),\n    defaultValues: {\n      email: \"\",\n      password: \"\",\n    },\n  });\n```\n\n```text\nexport const FormInput = <T extends FieldValues>(\n  props: FormElementProps<T>,\n) => {\n  return (\n    <FormField\n      control={props.form.control}\n      name={props.name}\n      render={({ field }) => (\n        <FormItem>\n          {props.label && <FormLabel>{props.label}</FormLabel>}\n\n          <FormControl>\n            <Input\n              {...field}\n              type={props.type}\n              disabled={props.disabled}\n              placeholder={props.placeholder}\n            />\n          </FormControl>\n\n          {props.description && (\n            <FormDescription>{props.description}</FormDescription>\n          )}\n\n          <FormMessage />\n        </FormItem>\n      )}\n    />\n  );\n};  \nFormInput.displayName = \"FormInput\";\n```\n\n```text\n{props.error && <span>{error.message}</span>}\n```\n\n```text\nloginForm\n```\n\n```text\nFormInput\n```\n\n```text\nprops\n```\n\n```text\nerrors\n```\n\n```text\nFormInput\n```\n\n```text\nFormInput\n```","metadata":{"transformedAt":"2026-08-18T18:33:48.871Z","totalAnswersIncluded":1,"totalCodeBlocksIncluded":14,"totalLines":304,"estimatedTokens":1449}}93{"id":"stack-72743126","source":"stackoverflow","questionId":72743126,"title":"How to get ZodError in json","tags":["javascript","typescript","validation","typeorm","zod"],"text":"Title: How to get ZodError in json\nTags: javascript, typescript, validation, typeorm, zod\nSource: Stack Overflow\n\nQuestion:\nI'm trying to get zod validation errors in json when i test it in insomnia, but am getting it only in terminal and in insomnia it's telling me Error: Couldn't connect to server\ni saw some examples and everywhere it's worked... don't understand why it's not working...\n\nmy register method\n\n```\nexport const register = async (req: Request, res: Response) => {\n const payloadSchema = z\n .object({\n firstname: z.string({\n required_error: \"Firstname is required\",\n invalid_type_error: \"Title must be a string\",\n }),\n lastname: z.string({\n required_error: \"Lastname is required\",\n invalid_type_error: \"Title must be a string\",\n }),\n email: z\n .string({ required_error: \"Email is required\" })\n .email({ message: \"Invalid email address\" }),\n password: z.string(),\n confirm: z.string(),\n })\n .refine((data) => data.password === data.confirm, {\n message: \"Passwords don't match\",\n path: [\"confirm\"], \n });\n\n const parsedData = await payloadSchema.parseAsync(req.body);\n\n try {\n const result = await User.findOne({ where: { email: parsedData.email } });\n\n if (result) {\n return res.status(400).json({\n success: false,\n error: \"User already exists\",\n });\n }\n\n const user = new User();\n user.firstname = parsedData.firstname;\n user.lastname = parsedData.lastname;\n user.email = parsedData.email;\n user.password = parsedData.password;\n await user.save();\n\n const accessToken = jwt.sign(\n { userId: user.id },\n process!.env!.TOKEN_SECRET!\n );\n\n return res.status(200).json({\n success: true,\n createdUser: user,\n accessToken: accessToken,\n });\n } catch (e) {\n if (e instanceof ZodError) {\n return res.status(400).json({\n success: false,\n error: e.flatten(),\n });\n } else if (e instanceof Error) {\n return res.status(400).json({\n message: e.message,\n });\n }\n }\n};\n```\n\nso what's am doing wrong, and how can i fix it? thanks for attention.\n\n========================================\n\nCode:\n```text\nexport const register = async (req: Request, res: Response) => {\n  const payloadSchema = z\n    .object({\n      firstname: z.string({\n        required_error: \"Firstname is required\",\n        invalid_type_error: \"Title must be a string\",\n      }),\n      lastname: z.string({\n        required_error: \"Lastname is required\",\n        invalid_type_error: \"Title must be a string\",\n      }),\n      email: z\n        .string({ required_error: \"Email is required\" })\n        .email({ message: \"Invalid email address\" }),\n      password: z.string(),\n      confirm: z.string(),\n    })\n    .refine((data) => data.password === data.confirm, {\n      message: \"Passwords don't match\",\n      path: [\"confirm\"], \n    });\n\n  const parsedData = await payloadSchema.parseAsync(req.body);\n\n  try {\n    const result = await User.findOne({ where: { email: parsedData.email } });\n\n    if (result) {\n      return res.status(400).json({\n        success: false,\n        error: \"User already exists\",\n      });\n    }\n\n    const user = new User();\n    user.firstname = parsedData.firstname;\n    user.lastname = parsedData.lastname;\n    user.email = parsedData.email;\n    user.password = parsedData.password;\n    await user.save();\n\n    const accessToken = jwt.sign(\n      { userId: user.id },\n      process!.env!.TOKEN_SECRET!\n    );\n\n    return res.status(200).json({\n      success: true,\n      createdUser: user,\n      accessToken: accessToken,\n    });\n  } catch (e) {\n    if (e instanceof ZodError) {\n      return res.status(400).json({\n        success: false,\n        error: e.flatten(),\n      });\n    } else if (e instanceof Error) {\n      return res.status(400).json({\n        message: e.message,\n      });\n    }\n  }\n};\n```\n\n```text\nconst parsedData = await payloadSchema.parseAsync(req.body);\n```\n\n```text\ntry {\n  const parsedData = await payloadSchema.parseAsync(req.body);\n \n  const result = await User.findOne({ where: { email: parsedData.email } });\n\n  ...\n```\n\n```text\nparseAsync\n```","metadata":{"transformedAt":"2026-08-18T18:33:48.871Z","totalAnswersIncluded":0,"totalCodeBlocksIncluded":4,"totalLines":165,"estimatedTokens":992}}94{"id":"stack-76396222","source":"stackoverflow","questionId":76396222,"title":"Zod - Using optional() with default() infers the wrong type","tags":["node.js","typescript","zod"],"text":"Title: Zod - Using optional() with default() infers the wrong type\nTags: node.js, typescript, zod\nSource: Stack Overflow\n\nQuestion:\nI'm using Zod with a field that is optional, but has a default value set, however, the inferred type says it could be undefined, even though it has a default value\n\n```\nconst Schema = z.object({\n page: z.number().positive().optional().default(1)\n})\n\ntype SchemaType = z.infer\n// page?: number | undefined;\n```\n\nI tried using `z.input` and `z.output`, but they don't work either.\n\nIs this intentional or is there another infer helper, which infers the parsed result?\n\n========================================\n\nCode:\n```text\nconst Schema = z.object({\n  page: z.number().positive().optional().default(1)\n})\n\ntype SchemaType = z.infer<typeof Schema>\n// page?: number | undefined;\n```\n\n```text\nz.input\n```\n\n```text\nz.output\n```\n\n```json\n// tsconfig.json\n{\n  // ...\n  \"compilerOptions\": {\n    // ...\n    \"strict\": true\n  }\n}\n```\n\n```text\ntsconfig.json\n```\n\n```text\n--strict\n```\n\n```text\nfalse\n```\n\n```text\ntsconfig.json\n```\n\n```text\nSchemaType\n```\n\n```text\n{ page: number }\n```\n\n```text\n{ page?: number }\n```\n\n========================================\n\nComments:\n- Does this answer your question? How to make an optional property with a default value in Zod\n- It seems like the issue is the same, but the solution is not very ergonomic, it uses multiple composed types. I cant use z.input on Schema, because that would make all of the optional fields optional in TS. I need a type based on the runtime output of the schema, but z.output does not infer that one properly\n- Wasn't the original question asking for `page?: number | undefined` -> `page?: number`?\n- @Shahriar No. The original question is about infering the type of the parsed result. `page` can't be missing or `undefined` in the parsed result because it has a default value of `1`.","metadata":{"transformedAt":"2026-08-18T18:33:48.871Z","totalAnswersIncluded":0,"totalCodeBlocksIncluded":11,"totalLines":86,"estimatedTokens":468}}95{"id":"stack-79150114","source":"stackoverflow","questionId":79150114,"title":"Approach for handling `discriminatedUnion` with `superRefine` with Zod","tags":["javascript","typescript","zod"],"text":"Title: Approach for handling `discriminatedUnion` with `superRefine` with Zod\nTags: javascript, typescript, zod\nSource: Stack Overflow\n\nQuestion:\n### Dynamic Validation Schema\n\n**Base Schema**: Create a base schema that contains common fields.\n\n**Dynamic Validations**:\n\n- **Code**: Implement dynamic validations based on the `code` field.\n\n- **Flag**: Use a flag passed as a parameter to determine if additional validations should be applied.\n\n- **Shared complex validations**: Use `superRefine` in the base schema to maintain shared validation logic across all schemas.\n\n### Code example\n\n```\ntype Codes = {\n One: 'one',\n Two: 'two',\n}\n\nconst BaseSchema = z.object({\n code,\n // ... other common fields\n}).superRefine((data, ctx) => {\n // Common complex validation logic\n});\n\nconst One = z.object({\n email,\n});\n// ... more specific schemas like `Two`\n\nconst FlaggedSchema = z.object({\n dateOfBirth,\n});\n\nconst createSchema = (code: Codes, isFlagged: boolean) => {\n const isOne = code === Codes.One\n const baseSchema = BaseSchema.extend({\n code: z.literal(code),\n ...(isOne ? One.shape : {}),\n ...(isFlagged ? FlaggedSchema.shape : {}),\n });\n\n return baseSchema;\n};\n\nexport const createMapSchema = (isFlagged: boolean) => {\n const schemas = Object.values(Codes).map((code) =>\n createSchema(code, isFlagged),\n );\n const unions = z.discriminatedUnion('code', schemas);\n const map = z.record(z.array(unions));\n const schema = z.object({\n types: map,\n });\n return schema;\n};\n```\n\n### Problem\n\n`superRefine` it cannot be applied to the base schema if you plan to use schema methods like merge afterward. This limitation arises because `superRefine` returns a `Zod effect`, which prevents further modifications to the schema.\n\nso, how to apply common complex validations(`refine` or `superRefine`) in the base schema but also running dynamic validations depending schema fields or external data?\n\n### Aditional notes\n\nI reviewed this question but I didn't see anything to use with this specific case\n\n========================================\n\nCode:\n```none\ntype Codes = {\n    One: 'one',\n    Two: 'two',\n}\n\nconst BaseSchema = z.object({\n    code,\n    // ... other common fields\n}).superRefine((data, ctx) => {\n    // Common complex validation logic\n});\n\nconst One = z.object({\n  email,\n});\n// ... more specific schemas like `Two`\n\nconst FlaggedSchema = z.object({\n  dateOfBirth,\n});\n\nconst createSchema = (code: Codes, isFlagged: boolean) => {\n    const isOne = code === Codes.One\n    const baseSchema = BaseSchema.extend({\n        code: z.literal(code),\n        ...(isOne ? One.shape : {}),\n        ...(isFlagged ? FlaggedSchema.shape : {}),\n    });\n\n    return baseSchema;\n};\n\nexport const createMapSchema = (isFlagged: boolean) => {\n  const schemas = Object.values(Codes).map((code) =>\n    createSchema(code, isFlagged),\n  );\n  const unions = z.discriminatedUnion('code', schemas);\n  const map = z.record(z.array(unions));\n  const schema = z.object({\n    types: map,\n  });\n  return schema;\n};\n```\n\n```text\ncode\n```\n\n```text\nsuperRefine\n```\n\n```text\nsuperRefine\n```\n\n```text\nsuperRefine\n```\n\n```text\nZod effect\n```\n\n```text\nrefine\n```\n\n```text\nsuperRefine\n```\n\n```none\nfunction applyToRefined(zodType: z.ZodType, method: string, ...args: any[]): z.ZodType{\n    const refinements: any[] = [];\n    while(zodType instanceof z.ZodEffects){\n        if(zodType._def?.effect?.type !== 'refinement'){\n            throw new Error('Cannot handle object that is not produced by .refine or .superRefine');\n        }\n        refinements.push(zodType._def.effect.refinement);\n        zodType = zodType._def.schema;\n    }\n\n    if(!zodType[method] || !zodType[method].apply){\n        throw new Error(`The schema of the ZodEffects object doesn't have the method ${method}`);\n    }\n    zodType = zodType[method].apply(zodType, args);\n    while(refinements.length > 0){\n        const refinement = refinements.shift();\n        zodType = zodType.superRefine(refinement);\n    }\n    return zodType;\n}\n```\n\n```none\nconst BaseSchema = z.object({\n        first: z.string(),\n        second: z.number(),\n    })\n    .superRefine((arg: any, ctx: any) => {\n        if(Math.round(arg.second) !== arg.second){\n            ctx.addIssue({\n                code: z.ZodIssueCode.invalid_type,\n                message: \".second should be integer\",\n            });\n        }\n    })\n    .refine((arg: any) => arg.first.length > 0, {\n        message: \".first should not be the empty string\"\n    });\n\nfunction dynamicExtend(zodType: z.ZodType, code: string, otherStringProp: string){\n    return applyToRefined(zodType, 'extend', {\n        code: z.literal(code),\n        [otherStringProp]: z.string()\n    });\n}\n\nconst BaseSchema1 = dynamicExtend(BaseSchema, 'one', 'andOne');\nconst BaseSchema2 = dynamicExtend(BaseSchema, 'two', 'andTwo');\n\nconsole.log(BaseSchema1.parse({first: 'one', second: 100, code: 'one', andOne: '1'}));\nconsole.log(BaseSchema2.parse({first: 'one', second: 100, code: 'two', andTwo: '2'}));\ntry{\n    console.log(BaseSchema1.parse({first: '', second: 100.1, code: 'one', andOne: '2'}));\n}\ncatch(err){\n    console.error(err);\n}\ntry{\n    console.log(BaseSchema1.parse({first: '', second: 100.1, code: 'two'}));\n    //see https://github.com/colinhacks/zod/discussions/2971#discussioncomment-7588935\n}\ncatch(err){\n    console.error(err);\n}\n```\n\n```none\nfunction combineRefined(\n    zodTypes: z.ZodType[],\n    combinatorFunction: (...args: z.ZodType[]) => z.ZodType\n): z.ZodType {\n    const refinements: any[] = [];\n    const zodSchemas: z.ZodType[] = [];\n    let zodType: z.ZodType;\n    for(zodType of zodTypes){\n        while(zodType instanceof z.ZodEffects){\n            if(zodType._def?.effect?.type !== 'refinement'){\n                throw new Error('Cannot handle object that is not produced by .refine or .superRefine');\n            }\n            refinements.push(zodType._def.effect.refinement);\n            zodType = zodType._def.schema;\n        }\n        zodSchemas.push(zodType);\n    }\n    zodType = combinatorFunction(...zodSchemas);\n    while(refinements.length > 0){\n        const refinement = refinements.shift();\n        zodType = zodType.superRefine(refinement);\n    }\n    return zodType;\n}\n\n\n// create the union of the BaseSchema1, BaseSchema2 above, discriminated by \"code\" property\nconst BaseSchema12 = combineRefined([BaseSchema1, BaseSchema2],\n    (...schemas: z.ZodType[]) => z.discriminatedUnion(\"code\", schemas));\n```\n\n```none\nconsole.log('--------------------');\nconsole.log(BaseSchema12.parse({code: 'one', first: 'one', second: 100, andOne: '1'}));\nconsole.log(BaseSchema12.parse({code: 'two', first: 'one', second: 100, andTwo: '2'}));\ntry{\n    console.log(BaseSchema12.parse({code: 'one', first: 'one', second: 100, andTwo: '1'}));\n    // error: no andOne\n}\ncatch(err){\n    console.error(err);\n}\n\ntry{\n    console.log(BaseSchema12.parse({code: 'one', first: '', second: 100.1, andOne: '1'}));\n    // refine errors for first and second\n}\ncatch(err){\n    console.error(err);\n}\n```\n\n```text\nZodEffects\n```\n\n```text\nZodType\n```\n\n```text\n_def\n```\n\n```text\nZodEffects\n```\n\n```text\nzodEffects\n```\n\n```text\n.refine\n```\n\n```text\n.superRefine\n```\n\n```text\nzodEffects._def.schema\n```\n\n```text\nZodType\n```\n\n```text\n.refine\n```\n\n```text\n.superRefine\n```\n\n```text\nzodEffects._def.effect.refinement\n```\n\n```text\napplyToRefined\n```\n\n```text\nmethod\n```\n\n```text\nextend\n```\n\n```text\nzodType\n```\n\n```text\nZodObject\n```\n\n```text\nZodEffects\n```\n\n```text\nZodObject\n```\n\n```text\n_def\n```\n\n```text\nextend\n```\n\n```text\nZodEffect\n```\n\n```text\napplyToRefined\n```\n\n```text\nZodEffects\n```\n\n```text\n.parse\n```\n\n```text\nextend\n```\n\n```text\ndiscriminatedUnion\n```\n\n```text\nZodEffects\n```","metadata":{"transformedAt":"2026-08-18T18:33:48.871Z","totalAnswersIncluded":0,"totalCodeBlocksIncluded":40,"totalLines":383,"estimatedTokens":1914}}96