zod 3.25.71 → 3.25.73

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/index.cjs +2 -2
  2. package/index.d.cts +2 -2
  3. package/index.d.ts +2 -2
  4. package/index.js +2 -2
  5. package/package.json +1 -1
  6. package/src/index.ts +2 -2
  7. package/src/v4/classic/schemas.ts +4 -2
  8. package/src/v4/classic/tests/brand.test.ts +1 -3
  9. package/src/v4/classic/tests/discriminated-unions.test.ts +27 -0
  10. package/src/v4/classic/tests/index.test.ts +1 -1
  11. package/src/v4/classic/tests/object.test.ts +11 -1
  12. package/src/v4/classic/tests/optional.test.ts +20 -0
  13. package/src/v4/classic/tests/record.test.ts +7 -1
  14. package/src/v4/classic/tests/recursive-types.test.ts +3 -2
  15. package/src/v4/classic/tests/to-json-schema.test.ts +101 -1
  16. package/src/v4/core/schemas.ts +52 -18
  17. package/src/v4/core/to-json-schema.ts +16 -9
  18. package/src/v4/locales/eo.ts +125 -0
  19. package/src/v4/locales/index.ts +1 -0
  20. package/src/v4/mini/schemas.ts +2 -2
  21. package/src/v4/mini/tests/string.test.ts +6 -0
  22. package/v4/classic/schemas.cjs +1 -1
  23. package/v4/classic/schemas.d.cts +2 -1
  24. package/v4/classic/schemas.d.ts +2 -1
  25. package/v4/classic/schemas.js +1 -1
  26. package/v4/core/schemas.cjs +18 -5
  27. package/v4/core/schemas.d.cts +18 -9
  28. package/v4/core/schemas.d.ts +18 -9
  29. package/v4/core/schemas.js +18 -5
  30. package/v4/core/to-json-schema.cjs +3 -6
  31. package/v4/core/to-json-schema.d.cts +5 -1
  32. package/v4/core/to-json-schema.d.ts +5 -1
  33. package/v4/core/to-json-schema.js +3 -6
  34. package/v4/locales/eo.cjs +144 -0
  35. package/v4/locales/eo.d.cts +5 -0
  36. package/v4/locales/eo.d.ts +5 -0
  37. package/v4/locales/eo.js +116 -0
  38. package/v4/locales/index.cjs +3 -1
  39. package/v4/locales/index.d.cts +1 -0
  40. package/v4/locales/index.d.ts +1 -0
  41. package/v4/locales/index.js +1 -0
  42. package/v4/mini/schemas.cjs +1 -1
  43. package/v4/mini/schemas.d.cts +1 -1
  44. package/v4/mini/schemas.d.ts +1 -1
  45. package/v4/mini/schemas.js +1 -1
package/index.cjs CHANGED
@@ -27,7 +27,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
27
27
  };
28
28
  Object.defineProperty(exports, "__esModule", { value: true });
29
29
  exports.z = void 0;
30
- const z = __importStar(require("./v3/index.cjs"));
30
+ const z = __importStar(require("./v3/external.cjs"));
31
31
  exports.z = z;
32
- __exportStar(require("./v3/index.cjs"), exports);
32
+ __exportStar(require("./v3/external.cjs"), exports);
33
33
  exports.default = z;
package/index.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- import * as z from "./v3/index.cjs";
2
- export * from "./v3/index.cjs";
1
+ import * as z from "./v3/external.cjs";
2
+ export * from "./v3/external.cjs";
3
3
  export { z };
4
4
  export default z;
package/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import * as z from "./v3/index.js";
2
- export * from "./v3/index.js";
1
+ import * as z from "./v3/external.js";
2
+ export * from "./v3/external.js";
3
3
  export { z };
4
4
  export default z;
package/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import * as z from "./v3/index.js";
2
- export * from "./v3/index.js";
1
+ import * as z from "./v3/external.js";
2
+ export * from "./v3/external.js";
3
3
  export { z };
4
4
  export default z;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zod",
3
- "version": "3.25.71",
3
+ "version": "3.25.73",
4
4
  "type": "module",
5
5
  "author": "Colin McDonnell <zod@colinhacks.com>",
6
6
  "description": "TypeScript-first schema declaration and validation library with static type inference",
package/src/index.ts CHANGED
@@ -1,4 +1,4 @@
1
- import * as z from "./v3/index.js";
2
- export * from "./v3/index.js";
1
+ import * as z from "./v3/external.js";
2
+ export * from "./v3/external.js";
3
3
  export { z };
4
4
  export default z;
@@ -365,6 +365,8 @@ export const ZodString: core.$constructor<ZodString> = /*@__PURE__*/ core.$const
365
365
  inst.duration = (params) => inst.check(iso.duration(params as any));
366
366
  });
367
367
 
368
+ export function string(params?: string | core.$ZodStringParams): ZodString;
369
+ export function string<T extends string>(params?: string | core.$ZodStringParams): core.$ZodType<T, T>;
368
370
  export function string(params?: string | core.$ZodStringParams): ZodString {
369
371
  return core._string(ZodString, params) as any;
370
372
  }
@@ -1357,11 +1359,11 @@ export function partialRecord<Key extends core.$ZodRecordKey, Value extends core
1357
1359
  keyType: Key,
1358
1360
  valueType: Value,
1359
1361
  params?: string | core.$ZodRecordParams
1360
- ): ZodRecord<ZodUnion<[Key, ZodNever]>, Value> {
1362
+ ): ZodRecord<Key, ZodOptional<Value>> {
1361
1363
  return new ZodRecord({
1362
1364
  type: "record",
1363
1365
  keyType: union([keyType, never()]),
1364
- valueType: valueType as any as core.$ZodType,
1366
+ valueType: optional(valueType),
1365
1367
  ...util.normalizeParams(params),
1366
1368
  }) as any;
1367
1369
  }
@@ -59,7 +59,5 @@ test("$branded", () => {
59
59
  test("branded record", () => {
60
60
  const recordWithBrandedNumberKeys = z.record(z.string().brand("SomeBrand"), z.number());
61
61
  type recordWithBrandedNumberKeys = z.infer<typeof recordWithBrandedNumberKeys>;
62
- expectTypeOf<recordWithBrandedNumberKeys>().toEqualTypeOf<
63
- Record<string & z.core.$brand<"SomeBrand">, number | undefined>
64
- >();
62
+ expectTypeOf<recordWithBrandedNumberKeys>().toEqualTypeOf<Record<string & z.core.$brand<"SomeBrand">, number>>();
65
63
  });
@@ -24,6 +24,9 @@ test("_values", () => {
24
24
 
25
25
  const post = z.literal("test").transform((_) => Math.random());
26
26
  expect(post._zod.values).toEqual(new Set(["test"]));
27
+
28
+ // Test that readonly literals pass through their values property
29
+ expect(z.literal("test").readonly()._zod.values).toEqual(new Set(["test"]));
27
30
  });
28
31
 
29
32
  test("valid parse - object", () => {
@@ -590,3 +593,27 @@ test("nested discriminated unions", () => {
590
593
  }
591
594
  `);
592
595
  });
596
+
597
+ test("readonly literal discriminator", () => {
598
+ const discUnion = z.discriminatedUnion("type", [
599
+ z.object({ type: z.literal("a").readonly(), a: z.string() }),
600
+ z.object({ type: z.literal("b"), b: z.number() }),
601
+ ]);
602
+
603
+ // Test that both discriminator values are correctly included in propValues
604
+ const propValues = discUnion._zod.propValues;
605
+ expect(propValues?.type?.has("a")).toBe(true);
606
+ expect(propValues?.type?.has("b")).toBe(true);
607
+
608
+ // Test that the discriminated union works correctly
609
+ const result1 = discUnion.parse({ type: "a", a: "hello" });
610
+ expect(result1).toEqual({ type: "a", a: "hello" });
611
+
612
+ const result2 = discUnion.parse({ type: "b", b: 42 });
613
+ expect(result2).toEqual({ type: "b", b: 42 });
614
+
615
+ // Test that invalid discriminator values are rejected
616
+ expect(() => {
617
+ discUnion.parse({ type: "c", a: "hello" });
618
+ }).toThrow();
619
+ });
@@ -301,7 +301,7 @@ test("z.record", () => {
301
301
  // partial enum
302
302
  const d = z.record(z.enum(["a", "b"]).or(z.never()), z.string());
303
303
  type d = z.output<typeof d>;
304
- expectTypeOf<d>().toEqualTypeOf<Partial<Record<"a" | "b", string>>>();
304
+ expectTypeOf<d>().toEqualTypeOf<Record<"a" | "b", string>>();
305
305
  });
306
306
 
307
307
  test("z.map", () => {
@@ -217,6 +217,16 @@ test("test inferred merged type", async () => {
217
217
  expectTypeOf<asdf>().toEqualTypeOf<{ a: number }>();
218
218
  });
219
219
 
220
+ test("inferred type with Record shape", () => {
221
+ type A = z.ZodObject<Record<string, z.ZodType<string, number>>>;
222
+ expectTypeOf<z.infer<A>>().toEqualTypeOf<Record<string, string>>();
223
+ expectTypeOf<z.input<A>>().toEqualTypeOf<Record<string, number>>();
224
+
225
+ type B = z.ZodObject;
226
+ expectTypeOf<z.infer<B>>().toEqualTypeOf<Record<string, unknown>>();
227
+ expectTypeOf<z.input<B>>().toEqualTypeOf<Record<string, unknown>>();
228
+ });
229
+
220
230
  test("inferred merged object type with optional properties", async () => {
221
231
  const Merged = z
222
232
  .object({ a: z.string(), b: z.string().optional() })
@@ -549,5 +559,5 @@ test("index signature in shape", () => {
549
559
  const schema = makeZodObj("foo");
550
560
  type schema = z.infer<typeof schema>;
551
561
 
552
- expectTypeOf<schema>().toEqualTypeOf<Record<string, unknown>>();
562
+ expectTypeOf<schema>().toEqualTypeOf<Record<string, string>>();
553
563
  });
@@ -37,6 +37,26 @@ test("optionality", () => {
37
37
  const e = z.string().default("asdf").nullable();
38
38
  expect(e._zod.optin).toEqual("optional");
39
39
  expect(e._zod.optout).toEqual(undefined);
40
+
41
+ // z.undefined should NOT be optional
42
+ const f = z.undefined();
43
+ expect(f._zod.optin).toEqual("optional");
44
+ expect(f._zod.optout).toEqual("optional");
45
+ expectTypeOf<typeof f._zod.optin>().toEqualTypeOf<"optional" | undefined>();
46
+ expectTypeOf<typeof f._zod.optout>().toEqualTypeOf<"optional" | undefined>();
47
+
48
+ // z.union should be optional if any of the types are optional
49
+ const g = z.union([z.string(), z.undefined()]);
50
+ expect(g._zod.optin).toEqual("optional");
51
+ expect(g._zod.optout).toEqual("optional");
52
+ expectTypeOf<typeof g._zod.optin>().toEqualTypeOf<"optional" | undefined>();
53
+ expectTypeOf<typeof g._zod.optout>().toEqualTypeOf<"optional" | undefined>();
54
+
55
+ const h = z.union([z.string(), z.optional(z.string())]);
56
+ expect(h._zod.optin).toEqual("optional");
57
+ expect(h._zod.optout).toEqual("optional");
58
+ expectTypeOf<typeof h._zod.optin>().toEqualTypeOf<"optional">();
59
+ expectTypeOf<typeof h._zod.optout>().toEqualTypeOf<"optional">();
40
60
  });
41
61
 
42
62
  test("pipe optionality", () => {
@@ -17,7 +17,7 @@ test("type inference", () => {
17
17
  expectTypeOf<booleanRecord>().toEqualTypeOf<Record<string, boolean>>();
18
18
  expectTypeOf<recordWithEnumKeys>().toEqualTypeOf<Record<"Tuna" | "Salmon", string>>();
19
19
  expectTypeOf<recordWithLiteralKey>().toEqualTypeOf<Record<"Tuna" | "Salmon", string>>();
20
- expectTypeOf<recordWithLiteralUnionKeys>().toEqualTypeOf<Partial<Record<"Tuna" | "Salmon", string>>>();
20
+ expectTypeOf<recordWithLiteralUnionKeys>().toEqualTypeOf<Record<"Tuna" | "Salmon", string>>();
21
21
  });
22
22
 
23
23
  test("enum exhaustiveness", () => {
@@ -330,3 +330,9 @@ test("async parsing", async () => {
330
330
  ]]
331
331
  `);
332
332
  });
333
+
334
+ test("partial record", () => {
335
+ const schema = z.partialRecord(z.string(), z.string());
336
+ type schema = z.infer<typeof schema>;
337
+ expectTypeOf<schema>().toEqualTypeOf<Partial<Record<string, string>>>();
338
+ });
@@ -160,9 +160,10 @@ test("deferred self-recursion", () => {
160
160
  const Output = z.object({
161
161
  id: z.int(), //.nonnegative(),
162
162
  name: z.string(),
163
- features: z.array(Feature), //.array(), // <—
163
+ get features(): z.ZodArray<typeof Feature> {
164
+ return Feature.array();
165
+ },
164
166
  });
165
-
166
167
  type Output = z.output<typeof Output>;
167
168
 
168
169
  type _Feature = {
@@ -31,7 +31,7 @@ describe("toJSONSchema", () => {
31
31
  expect(z.toJSONSchema(z.undefined())).toMatchInlineSnapshot(`
32
32
  {
33
33
  "$schema": "https://json-schema.org/draft/2020-12/schema",
34
- "type": "null",
34
+ "not": {},
35
35
  }
36
36
  `);
37
37
  expect(z.toJSONSchema(z.any())).toMatchInlineSnapshot(`
@@ -1259,6 +1259,35 @@ test("override execution order", () => {
1259
1259
  `);
1260
1260
  });
1261
1261
 
1262
+ test("override with path", () => {
1263
+ const userSchema = z.object({
1264
+ name: z.string(),
1265
+ age: z.number(),
1266
+ });
1267
+
1268
+ const capturedPaths: (string | number)[][] = [];
1269
+
1270
+ z.toJSONSchema(userSchema, {
1271
+ override(ctx) {
1272
+ capturedPaths.push(ctx.path);
1273
+ },
1274
+ });
1275
+
1276
+ expect(capturedPaths).toMatchInlineSnapshot(`
1277
+ [
1278
+ [
1279
+ "properties",
1280
+ "age",
1281
+ ],
1282
+ [
1283
+ "properties",
1284
+ "name",
1285
+ ],
1286
+ [],
1287
+ ]
1288
+ `);
1289
+ });
1290
+
1262
1291
  test("pipe", () => {
1263
1292
  const mySchema = z
1264
1293
  .string()
@@ -1856,6 +1885,11 @@ test("input type", () => {
1856
1885
  c: z.string().default("hello"),
1857
1886
  d: z.string().nullable(),
1858
1887
  e: z.string().prefault("hello"),
1888
+ f: z.string().catch("hello"),
1889
+ g: z.never(),
1890
+ h: z.undefined(),
1891
+ i: z.union([z.string(), z.number().default(2)]),
1892
+ j: z.union([z.string(), z.string().optional()]),
1859
1893
  });
1860
1894
  expect(z.toJSONSchema(schema, { io: "input" })).toMatchInlineSnapshot(`
1861
1895
  {
@@ -1885,10 +1919,42 @@ test("input type", () => {
1885
1919
  "default": "hello",
1886
1920
  "type": "string",
1887
1921
  },
1922
+ "f": {
1923
+ "default": "hello",
1924
+ "type": "string",
1925
+ },
1926
+ "g": {
1927
+ "not": {},
1928
+ },
1929
+ "h": {
1930
+ "not": {},
1931
+ },
1932
+ "i": {
1933
+ "anyOf": [
1934
+ {
1935
+ "type": "string",
1936
+ },
1937
+ {
1938
+ "default": 2,
1939
+ "type": "number",
1940
+ },
1941
+ ],
1942
+ },
1943
+ "j": {
1944
+ "anyOf": [
1945
+ {
1946
+ "type": "string",
1947
+ },
1948
+ {
1949
+ "type": "string",
1950
+ },
1951
+ ],
1952
+ },
1888
1953
  },
1889
1954
  "required": [
1890
1955
  "a",
1891
1956
  "d",
1957
+ "g",
1892
1958
  ],
1893
1959
  "type": "object",
1894
1960
  }
@@ -1921,12 +1987,46 @@ test("input type", () => {
1921
1987
  "e": {
1922
1988
  "type": "string",
1923
1989
  },
1990
+ "f": {
1991
+ "default": "hello",
1992
+ "type": "string",
1993
+ },
1994
+ "g": {
1995
+ "not": {},
1996
+ },
1997
+ "h": {
1998
+ "not": {},
1999
+ },
2000
+ "i": {
2001
+ "anyOf": [
2002
+ {
2003
+ "type": "string",
2004
+ },
2005
+ {
2006
+ "default": 2,
2007
+ "type": "number",
2008
+ },
2009
+ ],
2010
+ },
2011
+ "j": {
2012
+ "anyOf": [
2013
+ {
2014
+ "type": "string",
2015
+ },
2016
+ {
2017
+ "type": "string",
2018
+ },
2019
+ ],
2020
+ },
1924
2021
  },
1925
2022
  "required": [
1926
2023
  "a",
1927
2024
  "c",
1928
2025
  "d",
1929
2026
  "e",
2027
+ "f",
2028
+ "g",
2029
+ "i",
1930
2030
  ],
1931
2031
  "type": "object",
1932
2032
  }
@@ -90,7 +90,7 @@ export interface _$ZodTypeInternals {
90
90
  // types: Types;
91
91
 
92
92
  /** @internal Randomly generated ID for this schema. */
93
- id: string;
93
+ // id: string;
94
94
 
95
95
  /** @internal List of deferred initializers. */
96
96
  deferred: util.AnyFunc[] | undefined;
@@ -171,8 +171,7 @@ export interface _$ZodType<T extends $ZodTypeInternals = $ZodTypeInternals>
171
171
 
172
172
  export const $ZodType: core.$constructor<$ZodType> = /*@__PURE__*/ core.$constructor("$ZodType", (inst, def) => {
173
173
  inst ??= {} as any;
174
- // avoids issues with using Math.random() in Next.js caching
175
- util.defineLazy(inst._zod, "id", () => def.type + "_" + util.randomString(10));
174
+
176
175
  inst._zod.def = def; // set _def property
177
176
  inst._zod.bag = inst._zod.bag || {}; // initialize _bag object
178
177
  inst._zod.version = version;
@@ -428,7 +427,9 @@ export const $ZodURL: core.$constructor<$ZodURL> = /*@__PURE__*/ core.$construct
428
427
  $ZodStringFormat.init(inst, def);
429
428
  inst._zod.check = (payload) => {
430
429
  try {
431
- const url = new URL(payload.value);
430
+ const orig = payload.value;
431
+ const url = new URL(orig);
432
+ const href = url.href;
432
433
 
433
434
  if (def.hostname) {
434
435
  def.hostname.lastIndex = 0;
@@ -460,6 +461,13 @@ export const $ZodURL: core.$constructor<$ZodURL> = /*@__PURE__*/ core.$construct
460
461
  }
461
462
  }
462
463
 
464
+ // payload.value = url.href;
465
+ if (!orig.endsWith("/") && href.endsWith("/")) {
466
+ payload.value = href.slice(0, -1);
467
+ } else {
468
+ payload.value = href;
469
+ }
470
+
463
471
  return;
464
472
  } catch (_) {
465
473
  payload.issues.push({
@@ -1238,6 +1246,8 @@ export const $ZodUndefined: core.$constructor<$ZodUndefined> = /*@__PURE__*/ cor
1238
1246
  $ZodType.init(inst, def);
1239
1247
  inst._zod.pattern = regexes.undefined;
1240
1248
  inst._zod.values = new Set([undefined]);
1249
+ inst._zod.optin = "optional";
1250
+ inst._zod.optout = "optional";
1241
1251
 
1242
1252
  inst._zod.parse = (payload, _ctx) => {
1243
1253
  const input = payload.value;
@@ -1374,7 +1384,6 @@ export interface $ZodNever extends $ZodType {
1374
1384
 
1375
1385
  export const $ZodNever: core.$constructor<$ZodNever> = /*@__PURE__*/ core.$constructor("$ZodNever", (inst, def) => {
1376
1386
  $ZodType.init(inst, def);
1377
-
1378
1387
  inst._zod.parse = (payload, _ctx) => {
1379
1388
  payload.issues.push({
1380
1389
  expected: "never",
@@ -1488,14 +1497,15 @@ export interface $ZodArrayDef<T extends SomeType = $ZodType> extends $ZodTypeDef
1488
1497
  element: T;
1489
1498
  }
1490
1499
 
1491
- export interface $ZodArrayInternals<T extends SomeType = $ZodType>
1492
- extends $ZodTypeInternals<core.output<T>[], core.input<T>[]> {
1500
+ export interface $ZodArrayInternals<T extends SomeType = $ZodType> extends _$ZodTypeInternals {
1501
+ //$ZodTypeInternals<core.output<T>[], core.input<T>[]> {
1493
1502
  def: $ZodArrayDef<T>;
1494
1503
  isst: errors.$ZodIssueInvalidType;
1504
+ output: core.output<T>[];
1505
+ input: core.input<T>[];
1495
1506
  }
1496
1507
 
1497
- export interface $ZodArray<T extends SomeType = $ZodType>
1498
- extends $ZodType<core.output<T>[], core.input<T>[], $ZodArrayInternals<T>> {}
1508
+ export interface $ZodArray<T extends SomeType = $ZodType> extends $ZodType<any, any, $ZodArrayInternals<T>> {}
1499
1509
 
1500
1510
  function handleArrayResult(result: ParsePayload<any>, final: ParsePayload<any[]>, index: number) {
1501
1511
  if (result.issues.length) {
@@ -1559,7 +1569,9 @@ type OptionalOutSchema = { _zod: { optout: "optional" } };
1559
1569
  type OptionalInSchema = { _zod: { optin: "optional" } };
1560
1570
 
1561
1571
  export type $InferObjectOutput<T extends $ZodLooseShape, Extra extends Record<string, unknown>> = string extends keyof T
1562
- ? Record<string, unknown>
1572
+ ? util.IsAny<T[keyof T]> extends true
1573
+ ? Record<string, unknown>
1574
+ : Record<string, core.output<T[keyof T]>>
1563
1575
  : keyof (T & Extra) extends never
1564
1576
  ? Record<string, never>
1565
1577
  : util.Prettify<
@@ -1571,7 +1583,9 @@ export type $InferObjectOutput<T extends $ZodLooseShape, Extra extends Record<st
1571
1583
  >;
1572
1584
 
1573
1585
  export type $InferObjectInput<T extends $ZodLooseShape, Extra extends Record<string, unknown>> = string extends keyof T
1574
- ? Record<string, unknown>
1586
+ ? util.IsAny<T[keyof T]> extends true
1587
+ ? Record<string, unknown>
1588
+ : Record<string, core.input<T[keyof T]>>
1575
1589
  : keyof (T & Extra) extends never
1576
1590
  ? Record<string, never>
1577
1591
  : util.Prettify<
@@ -1710,8 +1724,9 @@ export const $ZodObject: core.$constructor<$ZodObject> = /*@__PURE__*/ core.$con
1710
1724
  doc.write(`const input = payload.value;`);
1711
1725
 
1712
1726
  const ids: any = Object.create(null);
1727
+ let counter = 0;
1713
1728
  for (const key of normalized.keys) {
1714
- ids[key] = util.randomString(15);
1729
+ ids[key] = `key_${counter++}`;
1715
1730
  }
1716
1731
 
1717
1732
  // A: preserve key order {
@@ -1882,14 +1897,23 @@ export interface $ZodUnionDef<Options extends readonly SomeType[] = readonly $Zo
1882
1897
  options: Options;
1883
1898
  }
1884
1899
 
1885
- export interface $ZodUnionInternals<T extends readonly SomeType[] = readonly $ZodType[]>
1886
- extends $ZodTypeInternals<$InferUnionOutput<T[number]>, $InferUnionInput<T[number]>> {
1900
+ type IsOptionalIn<T extends SomeType> = T extends OptionalInSchema ? true : false;
1901
+ type IsOptionalOut<T extends SomeType> = T extends OptionalOutSchema ? true : false;
1902
+
1903
+ export interface $ZodUnionInternals<T extends readonly SomeType[] = readonly $ZodType[]> extends _$ZodTypeInternals {
1887
1904
  def: $ZodUnionDef<T>;
1888
1905
  isst: errors.$ZodIssueInvalidUnion;
1889
1906
  pattern: T[number]["_zod"]["pattern"];
1907
+ values: T[number]["_zod"]["values"]; //GetValues<T[number]>;
1908
+ output: $InferUnionOutput<T[number]>;
1909
+ input: $InferUnionInput<T[number]>;
1910
+ // if any element in the union is optional, then the union is optional
1911
+ optin: IsOptionalIn<T[number]> extends false ? "optional" | undefined : "optional";
1912
+ optout: IsOptionalOut<T[number]> extends false ? "optional" | undefined : "optional";
1890
1913
  }
1891
1914
 
1892
- export interface $ZodUnion<T extends readonly SomeType[] = readonly $ZodType[]> extends $ZodType {
1915
+ export interface $ZodUnion<T extends readonly SomeType[] = readonly $ZodType[]>
1916
+ extends $ZodType<any, any, $ZodUnionInternals<T>> {
1893
1917
  _zod: $ZodUnionInternals<T>;
1894
1918
  }
1895
1919
 
@@ -1914,6 +1938,14 @@ function handleUnionResults(results: ParsePayload[], final: ParsePayload, inst:
1914
1938
  export const $ZodUnion: core.$constructor<$ZodUnion> = /*@__PURE__*/ core.$constructor("$ZodUnion", (inst, def) => {
1915
1939
  $ZodType.init(inst, def);
1916
1940
 
1941
+ util.defineLazy(inst._zod, "optin", () =>
1942
+ def.options.some((o) => o._zod.optin === "optional") ? "optional" : undefined
1943
+ );
1944
+
1945
+ util.defineLazy(inst._zod, "optout", () =>
1946
+ def.options.some((o) => o._zod.optout === "optional") ? "optional" : undefined
1947
+ );
1948
+
1917
1949
  util.defineLazy(inst._zod, "values", () => {
1918
1950
  if (def.options.every((o) => o._zod.values)) {
1919
1951
  return new Set<util.Primitive>(def.options.flatMap((option) => Array.from(option._zod.values!)));
@@ -2354,7 +2386,7 @@ export type $InferZodRecordOutput<
2354
2386
  ? Record<core.output<Key>, core.output<Value>>
2355
2387
  : symbol extends core.output<Key>
2356
2388
  ? Record<core.output<Key>, core.output<Value>>
2357
- : Partial<Record<core.output<Key>, core.output<Value>>>
2389
+ : Record<core.output<Key>, core.output<Value>>
2358
2390
  : Record<core.output<Key>, core.output<Value>>;
2359
2391
 
2360
2392
  export type $InferZodRecordInput<
@@ -2367,7 +2399,7 @@ export type $InferZodRecordInput<
2367
2399
  ? Record<core.input<Key>, core.input<Value>>
2368
2400
  : symbol extends core.input<Key>
2369
2401
  ? Record<core.input<Key>, core.input<Value>>
2370
- : Partial<Record<core.input<Key>, core.input<Value>>>
2402
+ : Record<core.input<Key>, core.input<Value>>
2371
2403
  : Record<core.input<Key>, core.input<Value>>;
2372
2404
 
2373
2405
  export interface $ZodRecordInternals<Key extends $ZodRecordKey = $ZodRecordKey, Value extends SomeType = $ZodType>
@@ -3272,7 +3304,7 @@ export interface $ZodCatch<T extends SomeType = $ZodType> extends $ZodType {
3272
3304
 
3273
3305
  export const $ZodCatch: core.$constructor<$ZodCatch> = /*@__PURE__*/ core.$constructor("$ZodCatch", (inst, def) => {
3274
3306
  $ZodType.init(inst, def);
3275
- util.defineLazy(inst._zod, "optin", () => def.innerType._zod.optin);
3307
+ inst._zod.optin = "optional";
3276
3308
  util.defineLazy(inst._zod, "optout", () => def.innerType._zod.optout);
3277
3309
  util.defineLazy(inst._zod, "values", () => def.innerType._zod.values);
3278
3310
 
@@ -3417,6 +3449,7 @@ export interface $ZodReadonlyInternals<T extends SomeType = $ZodType>
3417
3449
  optout: T["_zod"]["optout"];
3418
3450
  isst: never;
3419
3451
  propValues: T["_zod"]["propValues"];
3452
+ values: T["_zod"]["values"];
3420
3453
  }
3421
3454
 
3422
3455
  export interface $ZodReadonly<T extends SomeType = $ZodType> extends $ZodType {
@@ -3428,6 +3461,7 @@ export const $ZodReadonly: core.$constructor<$ZodReadonly> = /*@__PURE__*/ core.
3428
3461
  (inst, def) => {
3429
3462
  $ZodType.init(inst, def);
3430
3463
  util.defineLazy(inst._zod, "propValues", () => def.innerType._zod.propValues);
3464
+ util.defineLazy(inst._zod, "values", () => def.innerType._zod.values);
3431
3465
  util.defineLazy(inst._zod, "optin", () => def.innerType._zod.optin);
3432
3466
  util.defineLazy(inst._zod, "optout", () => def.innerType._zod.optout);
3433
3467
 
@@ -17,9 +17,13 @@ interface JSONSchemaGeneratorParams {
17
17
  * - `"any"` — Unrepresentable types become `{}` */
18
18
  unrepresentable?: "throw" | "any";
19
19
  /** Arbitrary custom logic that can be used to modify the generated JSON Schema. */
20
- override?: (ctx: { zodSchema: schemas.$ZodTypes; jsonSchema: JSONSchema.BaseSchema }) => void;
20
+ override?: (ctx: {
21
+ zodSchema: schemas.$ZodTypes;
22
+ jsonSchema: JSONSchema.BaseSchema;
23
+ path: (string | number)[];
24
+ }) => void;
21
25
  /** Whether to extract the `"input"` or `"output"` type. Relevant to transforms, Error converting schema to JSONz, defaults, coerced primitives, etc.
22
- * - `"output" — Default. Convert the output schema.
26
+ * - `"output"` Default. Convert the output schema.
23
27
  * - `"input"` — Convert the input schema. */
24
28
  io?: "input" | "output";
25
29
  }
@@ -61,13 +65,19 @@ interface Seen {
61
65
  cycle?: (string | number)[] | undefined;
62
66
  isParent?: boolean | undefined;
63
67
  ref?: schemas.$ZodType | undefined | null;
68
+ /** JSON Schema property path for this schema */
69
+ path?: (string | number)[] | undefined;
64
70
  }
65
71
 
66
72
  export class JSONSchemaGenerator {
67
73
  metadataRegistry: $ZodRegistry<Record<string, any>>;
68
74
  target: "draft-7" | "draft-2020-12";
69
75
  unrepresentable: "throw" | "any";
70
- override: (ctx: { zodSchema: schemas.$ZodTypes; jsonSchema: JSONSchema.BaseSchema }) => void;
76
+ override: (ctx: {
77
+ zodSchema: schemas.$ZodTypes;
78
+ jsonSchema: JSONSchema.BaseSchema;
79
+ path: (string | number)[];
80
+ }) => void;
71
81
  io: "input" | "output";
72
82
 
73
83
  counter = 0;
@@ -110,7 +120,7 @@ export class JSONSchemaGenerator {
110
120
  }
111
121
 
112
122
  // initialize
113
- const result: Seen = { schema: {}, count: 1, cycle: undefined };
123
+ const result: Seen = { schema: {}, count: 1, cycle: undefined, path: _params.path };
114
124
  this.seen.set(schema, result);
115
125
 
116
126
  // custom method overrides default behavior
@@ -207,11 +217,6 @@ export class JSONSchemaGenerator {
207
217
  }
208
218
  break;
209
219
  }
210
- case "undefined": {
211
- const json = _json as JSONSchema.NullSchema;
212
- json.type = "null";
213
- break;
214
- }
215
220
  case "null": {
216
221
  _json.type = "null";
217
222
  break;
@@ -222,6 +227,7 @@ export class JSONSchemaGenerator {
222
227
  case "unknown": {
223
228
  break;
224
229
  }
230
+ case "undefined":
225
231
  case "never": {
226
232
  _json.not = {};
227
233
  break;
@@ -740,6 +746,7 @@ export class JSONSchemaGenerator {
740
746
  this.override({
741
747
  zodSchema: zodSchema as schemas.$ZodTypes,
742
748
  jsonSchema: schema,
749
+ path: seen.path ?? [],
743
750
  });
744
751
  };
745
752