zod 4.6.1 → 4.6.3

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 (68) hide show
  1. package/README.md +2 -2
  2. package/package.json +1 -1
  3. package/src/v4/classic/checks.ts +1 -0
  4. package/src/v4/classic/schemas.ts +3 -25
  5. package/src/v4/classic/tests/cyclic-data.test.ts +2 -11
  6. package/src/v4/classic/tests/firstparty.test.ts +0 -4
  7. package/src/v4/classic/tests/instanceof.test.ts +1 -1
  8. package/src/v4/classic/tests/prefault.test.ts +70 -0
  9. package/src/v4/classic/tests/properties.test.ts +34 -137
  10. package/src/v4/core/api.ts +4 -7
  11. package/src/v4/core/checks.ts +61 -1
  12. package/src/v4/core/compile.ts +16 -24
  13. package/src/v4/core/json-schema-processors.ts +0 -50
  14. package/src/v4/core/memoizer.ts +2 -5
  15. package/src/v4/core/schemas.ts +10 -107
  16. package/src/v4/core/to-json-schema.ts +1 -1
  17. package/src/v4/core/util.ts +0 -4
  18. package/src/v4/core/versions.ts +1 -1
  19. package/src/v4/core/visit.ts +0 -11
  20. package/src/v4/mini/checks.ts +1 -0
  21. package/src/v4/mini/schemas.ts +1 -20
  22. package/src/v4/mini/tests/index.test.ts +22 -0
  23. package/v4/classic/checks.cjs +2 -1
  24. package/v4/classic/checks.d.cts +1 -1
  25. package/v4/classic/checks.d.ts +1 -1
  26. package/v4/classic/checks.js +1 -1
  27. package/v4/classic/schemas.cjs +2 -11
  28. package/v4/classic/schemas.d.cts +1 -6
  29. package/v4/classic/schemas.d.ts +1 -6
  30. package/v4/classic/schemas.js +1 -9
  31. package/v4/core/api.cjs +2 -3
  32. package/v4/core/api.d.cts +2 -2
  33. package/v4/core/api.d.ts +2 -2
  34. package/v4/core/api.js +2 -3
  35. package/v4/core/checks.cjs +32 -1
  36. package/v4/core/checks.d.cts +16 -0
  37. package/v4/core/checks.d.ts +16 -0
  38. package/v4/core/checks.js +31 -0
  39. package/v4/core/compile.cjs +12 -17
  40. package/v4/core/compile.js +12 -17
  41. package/v4/core/json-schema-processors.cjs +1 -34
  42. package/v4/core/json-schema-processors.d.cts +0 -1
  43. package/v4/core/json-schema-processors.d.ts +0 -1
  44. package/v4/core/json-schema-processors.js +1 -33
  45. package/v4/core/memoizer.cjs +2 -5
  46. package/v4/core/memoizer.js +2 -5
  47. package/v4/core/schemas.cjs +10 -70
  48. package/v4/core/schemas.d.cts +3 -20
  49. package/v4/core/schemas.d.ts +3 -20
  50. package/v4/core/schemas.js +9 -69
  51. package/v4/core/to-json-schema.cjs +0 -1
  52. package/v4/core/to-json-schema.d.cts +0 -3
  53. package/v4/core/to-json-schema.d.ts +0 -3
  54. package/v4/core/to-json-schema.js +1 -1
  55. package/v4/core/util.cjs +0 -4
  56. package/v4/core/util.js +0 -4
  57. package/v4/core/versions.cjs +1 -1
  58. package/v4/core/versions.js +1 -1
  59. package/v4/core/visit.cjs +0 -12
  60. package/v4/core/visit.js +0 -12
  61. package/v4/mini/checks.cjs +2 -1
  62. package/v4/mini/checks.d.cts +1 -1
  63. package/v4/mini/checks.d.ts +1 -1
  64. package/v4/mini/checks.js +1 -1
  65. package/v4/mini/schemas.cjs +1 -9
  66. package/v4/mini/schemas.d.cts +1 -5
  67. package/v4/mini/schemas.d.ts +1 -5
  68. package/v4/mini/schemas.js +0 -7
@@ -18,7 +18,7 @@ import {
18
18
  urlHostnameOk,
19
19
  urlProtocolOk,
20
20
  } from "./schemas.js";
21
- import type { $ZodProperties, $ZodPropertiesDef, ParseContextInternal, ParsePayload, SomeType } from "./schemas.js";
21
+ import type { ParseContextInternal, ParsePayload, SomeType } from "./schemas.js";
22
22
  import * as util from "./util.js";
23
23
 
24
24
  /** @internal Sentinel the compiled fast path returns when validation fails. */
@@ -89,7 +89,7 @@ type SupportedCheck =
89
89
  | checks.$ZodCheckLengthEquals
90
90
  | checks.$ZodCheckStringFormat
91
91
  | checks.$ZodCheckProperty
92
- | $ZodProperties
92
+ | checks.$ZodCheckProperties
93
93
  | checks.$ZodCheckMimeType
94
94
  | checks.$ZodCheckOverwrite
95
95
  | { _zod: { def: { check: "custom"; fn?: (value: unknown) => boolean }; check?: (payload: unknown) => unknown } };
@@ -455,7 +455,7 @@ function generateChecks(doc: Doc, ctx: CompileContext, schema: SomeType, accesso
455
455
  generatePropertyCheck(doc, ctx, def, currentAccessor);
456
456
  break;
457
457
  case "properties":
458
- generatePropertiesChecks(doc, ctx, def, currentAccessor, false);
458
+ generatePropertiesChecks(doc, ctx, def, currentAccessor);
459
459
  break;
460
460
  case "overwrite": {
461
461
  // Overwrite transforms the value - create new variable for transformed result
@@ -616,20 +616,15 @@ function generateMimeTypeCheck(
616
616
  function generatePropertiesChecks(
617
617
  doc: Doc,
618
618
  ctx: CompileContext,
619
- def: $ZodPropertiesDef,
620
- accessor: string,
621
- schemaRole: boolean
619
+ def: checks.$ZodCheckPropertiesDef,
620
+ accessor: string
622
621
  ): void {
623
- // a custom `when` gates the assertion at runtime; inside a union a wrongly-run branch is absorbed as a branch failure rather than falling back, so refuse at codegen the way the check role does
622
+ // a custom `when` gates the assertion at runtime; inside a union a wrongly-run branch is absorbed as a branch failure rather than falling back, so refuse at codegen
624
623
  if (def.when) {
625
624
  throw new ZodCompileUnsupportedError(`check with a custom "when" condition`);
626
625
  }
627
- // matches the runtime gate for whichever role this is: a schema rejects a primitive outright, a check only a nullish value
628
- doc.write(
629
- schemaRole
630
- ? `if (${accessor} === null || (typeof ${accessor} !== "object" && typeof ${accessor} !== "function")) return INVALID;`
631
- : `if (${accessor} == null) return INVALID;`
632
- );
626
+ // matches the runtime gate: the base schema already typed the value, so only a nullish one is rejected
627
+ doc.write(`if (${accessor} == null) return INVALID;`);
633
628
  const shape = def.shape as Record<string | symbol, SomeType>;
634
629
  for (const key of Reflect.ownKeys(shape)) {
635
630
  // a symbol has no source literal, so it is hoisted as a constant
@@ -934,7 +929,6 @@ type SupportedSchemaType =
934
929
  | "lazy"
935
930
  | "pipe"
936
931
  | "custom"
937
- | "properties"
938
932
  | "transform"
939
933
  | "catch";
940
934
 
@@ -1079,10 +1073,6 @@ function generateCheck(
1079
1073
  case "custom":
1080
1074
  typeAccessor = generateCustomCheck(doc, ctx, schema, accessor);
1081
1075
  break;
1082
- case "properties":
1083
- generatePropertiesChecks(doc, ctx, (schema as $ZodProperties)._zod.def, accessor, true);
1084
- typeAccessor = accessor;
1085
- break;
1086
1076
  case "transform":
1087
1077
  typeAccessor = generateTransformCheck(doc, ctx, schema, accessor);
1088
1078
  break;
@@ -1270,9 +1260,9 @@ function generateObjectCheck(
1270
1260
  }
1271
1261
  // else: strip mode (no catchall) - unknown keys ignored, only include known keys
1272
1262
 
1273
- // Shape keys in declared order, then unknown keys in for...in order. A middle-rung key is included iff present on the input, else iff its output is not undefined.
1263
+ // defaulted required outputs keep their keys even when undefined
1274
1264
  const outputVar = newVar(ctx);
1275
- const hasConditionalKeys = allKeys.some((k) => mayOutputUndefined(propShape[k]!) || dropsWhenAbsent(propShape[k]!));
1265
+ const hasConditionalKeys = allKeys.some((k) => mayOmitUndefined(propShape[k]!) || dropsWhenAbsent(propShape[k]!));
1276
1266
 
1277
1267
  // Assert mode: every declared key is validated above, so the output literal and the unknown-key copy are pure waste. A `never` catchall already emitted its rejection loop; a schema catchall still has to validate the values it would otherwise have stored.
1278
1268
  if (!buildsValue) {
@@ -1301,7 +1291,7 @@ function generateObjectCheck(
1301
1291
  const out = propOutputs.get(k);
1302
1292
  if (dropsWhenAbsent(propShape[k]!)) {
1303
1293
  doc.write(`if (${kx} in ${accessor}) ${outputVar}[${kx}] = ${out};`);
1304
- } else if (mayOutputUndefined(propShape[k]!)) {
1294
+ } else if (mayOmitUndefined(propShape[k]!)) {
1305
1295
  doc.write(`if (${out} !== undefined || ${kx} in ${accessor}) ${outputVar}[${kx}] = ${out};`);
1306
1296
  } else {
1307
1297
  doc.write(`${outputVar}[${kx}] = ${out};`);
@@ -1464,9 +1454,11 @@ function dropsWhenAbsent(schema: SomeType): boolean {
1464
1454
  return schema._zod.optin === "optional" && schema._zod.optout === "optional";
1465
1455
  }
1466
1456
 
1467
- // Whether a schema's success-path output can be `undefined`. Object output
1468
- // assembly gives such props the runtime's value-or-presence inclusion rule;
1469
- // everything else keeps the unconditional object-literal slot.
1457
+ function mayOmitUndefined(schema: SomeType): boolean {
1458
+ return (schema._zod.optin !== "defaulted" || schema._zod.optout === "optional") && mayOutputUndefined(schema);
1459
+ }
1460
+
1461
+ // whether a schema's success-path output can be undefined
1470
1462
  function mayOutputUndefined(schema: SomeType): boolean {
1471
1463
  const def = schema._zod.def as {
1472
1464
  type: string;
@@ -16,7 +16,6 @@ import {
16
16
  finalize,
17
17
  handleUnrepresentable,
18
18
  initializeContext,
19
- isTransforming,
20
19
  processSchema,
21
20
  } from "./to-json-schema.js";
22
21
  import { BIGINT_FORMAT_RANGES, NUMBER_FORMAT_RANGES, assignProp, getEnumValues } from "./util.js";
@@ -481,54 +480,6 @@ export const objectProcessor: Processor<schemas.$ZodObject> = (schema, ctx, _jso
481
480
  }
482
481
  };
483
482
 
484
- // asserts named properties in place and passes everything else through, so no additionalProperties constraint is emitted
485
- export const propertiesProcessor: Processor<schemas.$ZodProperties> = (schema, ctx, _json, params) => {
486
- const json = _json as JSONSchema.ObjectSchema;
487
- const def = schema._zod.def;
488
-
489
- // dropping a symbol key silently would emit a schema that asserts less than this one does
490
- if (
491
- Object.getOwnPropertySymbols(def.shape).length &&
492
- handleUnrepresentable(schema, ctx, json, params, "Symbol keys cannot be represented in JSON Schema")
493
- ) {
494
- return;
495
- }
496
-
497
- // the parsed value is the input, so an output-mode emission would describe a transformed value this schema never returns
498
- if (ctx.io === "output") {
499
- for (const key in def.shape) {
500
- if (
501
- isTransforming(def.shape[key]!) &&
502
- handleUnrepresentable(
503
- schema,
504
- ctx,
505
- json,
506
- params,
507
- `z.properties() returns its input, so the output of a transforming schema at key "${key}" cannot be represented in JSON Schema`
508
- )
509
- ) {
510
- return;
511
- }
512
- }
513
- }
514
-
515
- json.type = "object";
516
- json.properties = {};
517
- for (const key in def.shape) {
518
- assignProp(
519
- json.properties,
520
- key,
521
- processSchema(def.shape[key]!, ctx as any, {
522
- ...params,
523
- path: [...params.path, "properties", key],
524
- })
525
- );
526
- }
527
- // input-side optionality in both modes: the parsed value is the input, so a defaulted key that stays absent must not be required of the output either
528
- const required = Object.keys(def.shape).filter((key) => inputOptin(def.shape[key]!) === undefined);
529
- if (required.length > 0) json.required = required;
530
- };
531
-
532
483
  export const unionProcessor: Processor<schemas.$ZodUnion> = (schema, ctx, json, params) => {
533
484
  const def = schema._zod.def as schemas.$ZodUnionDef;
534
485
  // Exclusive unions (inclusive === false) use oneOf (exactly one match) instead of anyOf (one or more matches). This includes both z.xor() and discriminated unions
@@ -904,7 +855,6 @@ export const allProcessors: Record<string, Processor<any>> = {
904
855
  file: fileProcessor,
905
856
  success: successProcessor,
906
857
  custom: customProcessor,
907
- properties: propertiesProcessor,
908
858
  function: functionProcessor,
909
859
  transform: transformProcessor,
910
860
  map: mapProcessor,
@@ -28,9 +28,9 @@ type WithState = { [STATE]?: State };
28
28
 
29
29
  const NO_ISSUES: errors.$ZodRawIssue[] = [];
30
30
 
31
- // a value a cycle can close through; callables count, since z.properties asserts on one
31
+ // a value a cycle can close through
32
32
  function isRef(value: unknown): value is object {
33
- return value !== null && (typeof value === "object" || typeof value === "function");
33
+ return value !== null && typeof value === "object";
34
34
  }
35
35
 
36
36
  // Receivers prefix paths in place, so the cache and every hand-out need their own copies.
@@ -90,9 +90,6 @@ function isRecursive(inst: $ZodType, stack: Set<object>, resolve: boolean): Answ
90
90
  check(def.catchall);
91
91
  break;
92
92
  }
93
- case "properties":
94
- merge(shape(def.shape, false));
95
- break;
96
93
  case "array":
97
94
  check(def.element);
98
95
  break;
@@ -96,8 +96,7 @@ export interface $ZodTypeDef {
96
96
  | "promise"
97
97
  | "lazy"
98
98
  | "function"
99
- | "custom"
100
- | "properties";
99
+ | "custom";
101
100
  error?: errors.$ZodErrorMap<never> | undefined;
102
101
  checks?: checks.$ZodCheck<never>[];
103
102
  }
@@ -1983,7 +1982,7 @@ function handlePropertyResult(
1983
1982
  }
1984
1983
 
1985
1984
  if (result.value === undefined) {
1986
- if (isPresent) {
1985
+ if (isPresent || (optin === "defaulted" && !isOptionalOut)) {
1987
1986
  (final.value as any)[key] = undefined;
1988
1987
  }
1989
1988
  } else {
@@ -2314,16 +2313,16 @@ export const $ZodObjectJIT: core.$constructor<$ZodObject> = /*@__PURE__*/ core.$
2314
2313
  doc.write(`
2315
2314
  if (${id}.issues.length) {${prefixStr(id, k)}
2316
2315
  }
2317
-
2318
- if (${id}.value === undefined) {
2319
- if (${isPresent}) {
2320
- newResult[${k}] = undefined;
2321
- }
2322
- } else {
2316
+ `);
2317
+ if (optin === "defaulted") {
2318
+ doc.write(`newResult[${k}] = ${id}.value;`);
2319
+ } else {
2320
+ doc.write(`
2321
+ if (${id}.value !== undefined || ${isPresent}) {
2323
2322
  newResult[${k}] = ${id}.value;
2324
2323
  }
2325
-
2326
2324
  `);
2325
+ }
2327
2326
  }
2328
2327
  }
2329
2328
 
@@ -4077,7 +4076,7 @@ export interface $ZodPrefaultDef<T extends SomeType = $ZodType> extends $ZodType
4077
4076
  }
4078
4077
 
4079
4078
  export interface $ZodPrefaultInternals<T extends SomeType = $ZodType>
4080
- extends $ZodTypeInternals<util.NoUndefined<core.output<T>>, core.input<T> | undefined> {
4079
+ extends $ZodTypeInternals<core.output<T>, core.input<T> | undefined> {
4081
4080
  def: $ZodPrefaultDef<T>;
4082
4081
  optin: "defaulted";
4083
4082
  optout?: "optional" | undefined;
@@ -5096,101 +5095,6 @@ function handleRefineResult(result: unknown, payload: ParsePayload, input: unkno
5096
5095
  }
5097
5096
  }
5098
5097
 
5099
- ////////////////////////////////////////
5100
- ////////////////////////////////////////
5101
- ////////// //////////
5102
- ////////// $ZodProperties //////////
5103
- ////////// //////////
5104
- ////////////////////////////////////////
5105
- ////////////////////////////////////////
5106
- export interface $ZodPropertiesDef<Shape extends $ZodShape = $ZodShape> extends $ZodTypeDef, checks.$ZodCheckDef {
5107
- type: "properties";
5108
- check: "properties";
5109
- shape: Shape;
5110
- }
5111
-
5112
- // both sides infer the INPUT type: the shape is asserted and its results discarded, so a default, catch or transform inside it would make an output-typed inference a lie. The check side widens a literal to its primitive, so spreading over a `string` property still type-checks (#6520).
5113
- export interface $ZodPropertiesInternals<Shape extends $ZodShape = $ZodShape>
5114
- extends $ZodTypeInternals<$InferObjectInput<Shape, {}>, $InferObjectInput<Shape, {}>>,
5115
- checks.$ZodCheckInternals<{ -readonly [k in keyof Shape]: util.Widen<core.input<Shape[k]>> }> {
5116
- def: $ZodPropertiesDef<Shape>;
5117
- isst: errors.$ZodIssueInvalidType;
5118
- issc: errors.$ZodIssue;
5119
- }
5120
-
5121
- export interface $ZodProperties<Shape extends $ZodShape = $ZodShape> extends $ZodType {
5122
- _zod: $ZodPropertiesInternals<Shape>;
5123
- // yields the schema itself, so pre-4.6 `.check(...z.properties(shape))` spread call sites keep working
5124
- [Symbol.iterator](): Iterator<this>;
5125
- }
5126
-
5127
- // asserts in place: the child result's value is discarded, matching z.property(), because a nested object or array schema rebuilds its output even when nothing transformed
5128
- function handlePropertiesResult(result: ParsePayload, payload: ParsePayload, key: string | symbol): void {
5129
- if (result.issues.length) {
5130
- payload.issues.push(...util.prefixIssues(key, result.issues));
5131
- }
5132
- }
5133
-
5134
- export const $ZodProperties: core.$constructor<$ZodProperties> = /*@__PURE__*/ core.$constructor(
5135
- "$ZodProperties",
5136
- (inst, def) => {
5137
- // $ZodType.init prepends an instance that already carries the $ZodCheck trait to its own `checks`, which would run the shape a second time and cost the parse context. Initializing the check trait after it keeps the schema role in `parse`, where the context arrives.
5138
- $ZodType.init(inst, def);
5139
- checks.$ZodCheck.init(inst, def);
5140
-
5141
- const memo = core.globalConfig.memoizer;
5142
- memo?.attach(inst);
5143
-
5144
- // key and schema snapshotted together: reading one live and the other cached lets a later mutation of the caller's shape object pair a stale key with a missing schema
5145
- let entries!: [string | symbol, $ZodType][];
5146
- const runShape = (payload: ParsePayload, ctx: ParseContextInternal): util.MaybeAsync<void> => {
5147
- entries ??= Reflect.ownKeys(def.shape).map((key) => [key, (def.shape as any)[key] as $ZodType]);
5148
- const input = payload.value as any;
5149
- let proms: Promise<any>[] | undefined;
5150
- for (const [key, schema] of entries) {
5151
- const result = schema._zod.run({ value: input[key], issues: [] }, ctx);
5152
- if (result instanceof Promise) {
5153
- proms ??= [];
5154
- proms.push(result.then((result) => handlePropertiesResult(result, payload, key)));
5155
- } else {
5156
- handlePropertiesResult(result, payload, key);
5157
- }
5158
- }
5159
- if (proms) return Promise.all(proms).then(() => undefined);
5160
- return undefined;
5161
- };
5162
-
5163
- inst._zod.parse = (payload, ctx) => {
5164
- const input = payload.value;
5165
- // as a schema this is the type gate, and it infers an object shape, so a primitive is a type error. A function passes: its properties read like any other object's, and z.instanceof allows one.
5166
- if (input === null || (typeof input !== "object" && typeof input !== "function")) {
5167
- payload.issues.push({ expected: "object", code: "invalid_type", input, inst });
5168
- return payload;
5169
- }
5170
- // both sides declare the shape's input type, so the assertion runs forward in either direction; encoding the children backward would reject the very type this schema claims to take
5171
- if (ctx.direction === "backward") ctx = { ...ctx, direction: "forward" };
5172
- // the input is its own output here, so it registers as its own memo entry: a cycle re-entering this node hits the bucket instead of recursing forever
5173
- if (memo) memo.alloc(inst, payload, input, ctx);
5174
- const result = runShape(payload, ctx);
5175
- return result instanceof Promise ? result.then(() => payload) : payload;
5176
- };
5177
-
5178
- // as a check the base schema already typed the value, so this only asserts the properties — which read on a primitive too, matching z.property() on a string's length. It gets no context of its own, so a cycle through a spread schema is not tracked.
5179
- inst._zod.check = (payload) => {
5180
- if (payload.value == null) {
5181
- payload.issues.push({ expected: "object", code: "invalid_type", input: payload.value, inst });
5182
- return undefined;
5183
- }
5184
- return runShape(payload, {});
5185
- };
5186
- },
5187
- {
5188
- *[Symbol.iterator]() {
5189
- yield this;
5190
- },
5191
- }
5192
- );
5193
-
5194
5098
  export type $ZodTypes =
5195
5099
  | $ZodString
5196
5100
  | $ZodNumber
@@ -5223,7 +5127,6 @@ export type $ZodTypes =
5223
5127
  | $ZodPrefault
5224
5128
  | $ZodTemplateLiteral
5225
5129
  | $ZodCustom
5226
- | $ZodProperties
5227
5130
  | $ZodTransform
5228
5131
  | $ZodNonOptional
5229
5132
  | $ZodReadonly
@@ -757,7 +757,7 @@ export function finalize<T extends schemas.$ZodType>(
757
757
  }
758
758
  }
759
759
 
760
- export function isTransforming(
760
+ function isTransforming(
761
761
  _schema: schemas.$ZodType,
762
762
  _ctx?: {
763
763
  seen: Set<schemas.$ZodType>;
@@ -1125,10 +1125,6 @@ export function members(proto: object, table: object): void {
1125
1125
  // a method materializes bound on first read, which is what keeps a detached member working: `const opt = schema.optional; opt()`
1126
1126
  else defineBound(proto, key, desc.value);
1127
1127
  }
1128
- // for..in sees no symbol keys, so well-known members like Symbol.iterator install here
1129
- for (const sym of Object.getOwnPropertySymbols(table)) {
1130
- defineBound(proto, sym, (table as any)[sym]);
1131
- }
1132
1128
  }
1133
1129
 
1134
1130
  /** Shadows a prototype member with an own value, so a getter that builds from the instance runs once. */
@@ -1,5 +1,5 @@
1
1
  export const version = {
2
2
  major: 4,
3
3
  minor: 6,
4
- patch: 1 as number,
4
+ patch: 3 as number,
5
5
  } as const;
@@ -158,17 +158,6 @@ export function visit(schema: schemas.SomeType, fnOrHandlers: VisitFn | VisitHan
158
158
  const { _cachedInner, ...rest } = def;
159
159
  return clone(s, { ...rest, getter: () => run(original()) });
160
160
  }
161
- case "properties": {
162
- const oldShape = def.shape as Record<string | symbol, AnyZod>;
163
- let changed = false;
164
- const newShape: Record<string | symbol, AnyZod> = {};
165
- for (const k of Reflect.ownKeys(oldShape)) {
166
- const mapped = run(oldShape[k]!);
167
- if (mapped !== oldShape[k]) changed = true;
168
- newShape[k] = mapped;
169
- }
170
- return changed ? clone(s, { ...def, shape: newShape }) : s;
171
- }
172
161
  // A leaf by choice: `parts` are regex fragments, not data positions.
173
162
  case "template_literal":
174
163
  // Leaves.
@@ -23,6 +23,7 @@ export {
23
23
  _startsWith as startsWith,
24
24
  _endsWith as endsWith,
25
25
  _property as property,
26
+ _properties as properties,
26
27
  _mime as mime,
27
28
  _overwrite as overwrite,
28
29
  _normalize as normalize,
@@ -1597,7 +1597,7 @@ export const ZodMiniPrefault: core.$constructor<ZodMiniPrefault> = /*@__PURE__*/
1597
1597
  // @__NO_SIDE_EFFECTS__
1598
1598
  export function prefault<T extends SomeType>(
1599
1599
  innerType: T,
1600
- defaultValue: util.NoUndefined<core.input<T>> | (() => util.NoUndefined<core.input<T>>)
1600
+ defaultValue: core.input<T> | (() => core.input<T>)
1601
1601
  ): ZodMiniPrefault<T> {
1602
1602
  return new ZodMiniPrefault({
1603
1603
  type: "prefault",
@@ -1866,25 +1866,6 @@ export const ZodMiniCustom: core.$constructor<ZodMiniCustom> = /*@__PURE__*/ cor
1866
1866
  }
1867
1867
  );
1868
1868
 
1869
- // ZodMiniProperties
1870
- export interface ZodMiniProperties<Shape extends core.$ZodShape = core.$ZodShape>
1871
- extends _ZodMiniType<core.$ZodPropertiesInternals<Shape>>,
1872
- core.$ZodProperties<Shape> {}
1873
- export const ZodMiniProperties: core.$constructor<ZodMiniProperties> = /*@__PURE__*/ core.$constructor(
1874
- "ZodMiniProperties",
1875
- (inst, def) => {
1876
- core.$ZodProperties.init(inst, def);
1877
- ZodMiniType.init(inst, def);
1878
- }
1879
- );
1880
-
1881
- export function properties<Shape extends core.$ZodShape>(
1882
- shape: Shape,
1883
- params?: string | core.$ZodPropertiesParams
1884
- ): ZodMiniProperties<Shape> {
1885
- return core._properties(ZodMiniProperties, shape, params) as any;
1886
- }
1887
-
1888
1869
  // custom checks
1889
1870
  // @__NO_SIDE_EFFECTS__
1890
1871
  export function check<O = unknown>(fn: core.CheckFn<O>, params?: string | core.$ZodCustomParams): core.$ZodCheck<O> {
@@ -165,6 +165,28 @@ test("z.iso.duration", () => {
165
165
  expect(z.safeParse(b, d2).success).toEqual(false);
166
166
  });
167
167
 
168
+ test("z.prefault preserves undefined output", async () => {
169
+ const field = z.prefault(z.union([z.string(), z.undefined()]), () => undefined);
170
+ const schema = z.object({ a: field });
171
+ expectTypeOf<z.output<typeof field>>().toEqualTypeOf<string | undefined>();
172
+ expectTypeOf<z.output<typeof schema>>().toEqualTypeOf<{ a: string | undefined }>();
173
+ expect(z.parse(schema, {})).toStrictEqual({ a: undefined });
174
+ expect(z.parse(schema, { a: undefined })).toStrictEqual({ a: undefined });
175
+ expect(z.parse(schema, { a: "value" })).toStrictEqual({ a: "value" });
176
+ expect(z.safeParse(schema, { a: 123 }).success).toBe(false);
177
+ expect(await z.parseAsync(schema, {})).toStrictEqual({ a: undefined });
178
+ expect(z.parse(z.object({ a: z.prefault(z.optional(z.string()), undefined) }), {})).toStrictEqual({ a: undefined });
179
+ const transformed = z.prefault(
180
+ z.pipe(
181
+ z.string(),
182
+ z.transform(() => undefined)
183
+ ),
184
+ "fallback"
185
+ );
186
+ expectTypeOf<z.output<typeof transformed>>().toEqualTypeOf<undefined>();
187
+ expect(z.parse(z.object({ a: transformed }), {})).toStrictEqual({ a: undefined });
188
+ });
189
+
168
190
  test("z.undefined", () => {
169
191
  const a = z.undefined();
170
192
  expect(z.parse(a, undefined)).toEqual(undefined);
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.slugify = exports.toUpperCase = exports.toLowerCase = exports.trim = exports.normalize = exports.overwrite = exports.mime = exports.property = exports.endsWith = exports.startsWith = exports.includes = exports.uppercase = exports.lowercase = exports.regex = exports.length = exports.minLength = exports.maxLength = exports.size = exports.minSize = exports.maxSize = exports.multipleOf = exports.nonnegative = exports.nonpositive = exports.negative = exports.positive = exports.gte = exports.gt = exports.lte = exports.lt = void 0;
3
+ exports.slugify = exports.toUpperCase = exports.toLowerCase = exports.trim = exports.normalize = exports.overwrite = exports.mime = exports.properties = exports.property = exports.endsWith = exports.startsWith = exports.includes = exports.uppercase = exports.lowercase = exports.regex = exports.length = exports.minLength = exports.maxLength = exports.size = exports.minSize = exports.maxSize = exports.multipleOf = exports.nonnegative = exports.nonpositive = exports.negative = exports.positive = exports.gte = exports.gt = exports.lte = exports.lt = void 0;
4
4
  var index_js_1 = require("../core/index.cjs");
5
5
  Object.defineProperty(exports, "lt", { enumerable: true, get: function () { return index_js_1._lt; } });
6
6
  Object.defineProperty(exports, "lte", { enumerable: true, get: function () { return index_js_1._lte; } });
@@ -24,6 +24,7 @@ Object.defineProperty(exports, "includes", { enumerable: true, get: function ()
24
24
  Object.defineProperty(exports, "startsWith", { enumerable: true, get: function () { return index_js_1._startsWith; } });
25
25
  Object.defineProperty(exports, "endsWith", { enumerable: true, get: function () { return index_js_1._endsWith; } });
26
26
  Object.defineProperty(exports, "property", { enumerable: true, get: function () { return index_js_1._property; } });
27
+ Object.defineProperty(exports, "properties", { enumerable: true, get: function () { return index_js_1._properties; } });
27
28
  Object.defineProperty(exports, "mime", { enumerable: true, get: function () { return index_js_1._mime; } });
28
29
  Object.defineProperty(exports, "overwrite", { enumerable: true, get: function () { return index_js_1._overwrite; } });
29
30
  Object.defineProperty(exports, "normalize", { enumerable: true, get: function () { return index_js_1._normalize; } });
@@ -1 +1 @@
1
- export { _lt as lt, _lte as lte, _gt as gt, _gte as gte, _positive as positive, _negative as negative, _nonpositive as nonpositive, _nonnegative as nonnegative, _multipleOf as multipleOf, _maxSize as maxSize, _minSize as minSize, _size as size, _maxLength as maxLength, _minLength as minLength, _length as length, _regex as regex, _lowercase as lowercase, _uppercase as uppercase, _includes as includes, _startsWith as startsWith, _endsWith as endsWith, _property as property, _mime as mime, _overwrite as overwrite, _normalize as normalize, _trim as trim, _toLowerCase as toLowerCase, _toUpperCase as toUpperCase, _slugify as slugify, type $RefinementCtx as RefinementCtx, } from "../core/index.cjs";
1
+ export { _lt as lt, _lte as lte, _gt as gt, _gte as gte, _positive as positive, _negative as negative, _nonpositive as nonpositive, _nonnegative as nonnegative, _multipleOf as multipleOf, _maxSize as maxSize, _minSize as minSize, _size as size, _maxLength as maxLength, _minLength as minLength, _length as length, _regex as regex, _lowercase as lowercase, _uppercase as uppercase, _includes as includes, _startsWith as startsWith, _endsWith as endsWith, _property as property, _properties as properties, _mime as mime, _overwrite as overwrite, _normalize as normalize, _trim as trim, _toLowerCase as toLowerCase, _toUpperCase as toUpperCase, _slugify as slugify, type $RefinementCtx as RefinementCtx, } from "../core/index.cjs";
@@ -1 +1 @@
1
- export { _lt as lt, _lte as lte, _gt as gt, _gte as gte, _positive as positive, _negative as negative, _nonpositive as nonpositive, _nonnegative as nonnegative, _multipleOf as multipleOf, _maxSize as maxSize, _minSize as minSize, _size as size, _maxLength as maxLength, _minLength as minLength, _length as length, _regex as regex, _lowercase as lowercase, _uppercase as uppercase, _includes as includes, _startsWith as startsWith, _endsWith as endsWith, _property as property, _mime as mime, _overwrite as overwrite, _normalize as normalize, _trim as trim, _toLowerCase as toLowerCase, _toUpperCase as toUpperCase, _slugify as slugify, type $RefinementCtx as RefinementCtx, } from "../core/index.js";
1
+ export { _lt as lt, _lte as lte, _gt as gt, _gte as gte, _positive as positive, _negative as negative, _nonpositive as nonpositive, _nonnegative as nonnegative, _multipleOf as multipleOf, _maxSize as maxSize, _minSize as minSize, _size as size, _maxLength as maxLength, _minLength as minLength, _length as length, _regex as regex, _lowercase as lowercase, _uppercase as uppercase, _includes as includes, _startsWith as startsWith, _endsWith as endsWith, _property as property, _properties as properties, _mime as mime, _overwrite as overwrite, _normalize as normalize, _trim as trim, _toLowerCase as toLowerCase, _toUpperCase as toUpperCase, _slugify as slugify, type $RefinementCtx as RefinementCtx, } from "../core/index.js";
@@ -1 +1 @@
1
- export { _lt as lt, _lte as lte, _gt as gt, _gte as gte, _positive as positive, _negative as negative, _nonpositive as nonpositive, _nonnegative as nonnegative, _multipleOf as multipleOf, _maxSize as maxSize, _minSize as minSize, _size as size, _maxLength as maxLength, _minLength as minLength, _length as length, _regex as regex, _lowercase as lowercase, _uppercase as uppercase, _includes as includes, _startsWith as startsWith, _endsWith as endsWith, _property as property, _mime as mime, _overwrite as overwrite, _normalize as normalize, _trim as trim, _toLowerCase as toLowerCase, _toUpperCase as toUpperCase, _slugify as slugify, } from "../core/index.js";
1
+ export { _lt as lt, _lte as lte, _gt as gt, _gte as gte, _positive as positive, _negative as negative, _nonpositive as nonpositive, _nonnegative as nonnegative, _multipleOf as multipleOf, _maxSize as maxSize, _minSize as minSize, _size as size, _maxLength as maxLength, _minLength as minLength, _length as length, _regex as regex, _lowercase as lowercase, _uppercase as uppercase, _includes as includes, _startsWith as startsWith, _endsWith as endsWith, _property as property, _properties as properties, _mime as mime, _overwrite as overwrite, _normalize as normalize, _trim as trim, _toLowerCase as toLowerCase, _toUpperCase as toUpperCase, _slugify as slugify, } from "../core/index.js";
@@ -27,7 +27,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
27
27
  };
28
28
  Object.defineProperty(exports, "__esModule", { value: true });
29
29
  exports.ZodIntersection = exports.ZodDiscriminatedUnion = exports.ZodXor = exports.ZodUnion = exports.ZodObject = exports.ZodArray = exports.ZodDate = exports.ZodVoid = exports.ZodNever = exports.ZodUnknown = exports.ZodAny = exports.ZodNull = exports.ZodUndefined = exports.ZodSymbol = exports.ZodBigIntFormat = exports.ZodBigInt = exports.ZodBoolean = exports.ZodNumberFormat = exports.ZodNumber = exports.ZodCustomStringFormat = exports.ZodJWT = exports.ZodIBAN = exports.ZodCreditCard = exports.ZodE164 = exports.ZodBase64URL = exports.ZodBase64 = exports.ZodCIDRv6 = exports.ZodCIDRv4 = exports.ZodIPv6 = exports.ZodMAC = exports.ZodIPv4 = exports.ZodKSUID = exports.ZodXID = exports.ZodULID = exports.ZodCUID2 = exports.ZodCUID = exports.ZodNanoID = exports.ZodEmoji = exports.ZodURL = exports.ZodUUID = exports.ZodGUID = exports.ZodEmail = exports.ZodISODuration = exports.ZodISOTime = exports.ZodISODate = exports.ZodISODateTime = exports.ZodStringFormat = exports.ZodString = exports._ZodString = exports.ZodType = void 0;
30
- exports.stringbool = exports.ZodInstanceOf = exports.meta = exports.describe = exports.ZodProperties = exports.ZodCustom = exports.ZodFunction = exports.ZodPromise = exports.ZodLazy = exports.ZodTemplateLiteral = exports.ZodReadonly = exports.ZodPreprocess = exports.ZodCodec = exports.ZodPipe = exports.ZodNaN = exports.ZodCatch = exports.ZodSuccess = exports.ZodNonOptional = exports.ZodPrefault = exports.ZodDefault = exports.ZodNullable = exports.ZodExactOptional = exports.ZodOptional = exports.ZodTransform = exports.ZodFile = exports.ZodLiteral = exports.ZodEnum = exports.ZodSet = exports.ZodMap = exports.ZodRecord = exports.ZodTuple = void 0;
30
+ exports.stringbool = exports.ZodInstanceOf = exports.meta = exports.describe = exports.ZodCustom = exports.ZodFunction = exports.ZodPromise = exports.ZodLazy = exports.ZodTemplateLiteral = exports.ZodReadonly = exports.ZodPreprocess = exports.ZodCodec = exports.ZodPipe = exports.ZodNaN = exports.ZodCatch = exports.ZodSuccess = exports.ZodNonOptional = exports.ZodPrefault = exports.ZodDefault = exports.ZodNullable = exports.ZodExactOptional = exports.ZodOptional = exports.ZodTransform = exports.ZodFile = exports.ZodLiteral = exports.ZodEnum = exports.ZodSet = exports.ZodMap = exports.ZodRecord = exports.ZodTuple = void 0;
31
31
  exports.string = string;
32
32
  exports.email = email;
33
33
  exports.guid = guid;
@@ -118,7 +118,6 @@ exports._function = _function;
118
118
  exports.function = _function;
119
119
  exports._function = _function;
120
120
  exports.function = _function;
121
- exports.properties = properties;
122
121
  exports.check = check;
123
122
  exports.custom = custom;
124
123
  exports.refine = refine;
@@ -1577,14 +1576,6 @@ exports.ZodCustom = core.$constructor("ZodCustom", (inst, def) => {
1577
1576
  exports.ZodType.init(inst, def);
1578
1577
  inst._zod.processJSONSchema = (ctx, json, params) => processors.customProcessor(inst, ctx, json, params);
1579
1578
  });
1580
- exports.ZodProperties = core.$constructor("ZodProperties", (inst, def) => {
1581
- _ensureDefaultMemoizer();
1582
- core.$ZodProperties.init(inst, def);
1583
- exports.ZodType.init(inst, def);
1584
- });
1585
- function properties(shape, params) {
1586
- return core._properties(exports.ZodProperties, shape, params);
1587
- }
1588
1579
  // custom checks
1589
1580
  function check(fn) {
1590
1581
  const ch = new core.$ZodCheck({
@@ -1612,7 +1603,7 @@ exports.ZodInstanceOf = core.$constructor("ZodInstanceOf", (inst, def) => {
1612
1603
  }, {
1613
1604
  properties(shape, params) {
1614
1605
  // asserts in place, so the narrowed output type is truthful without a wrapper
1615
- return this.check(properties(shape, params));
1606
+ return this.check(core._properties(shape, params));
1616
1607
  },
1617
1608
  });
1618
1609
  function _instanceof(cls, params = {}) {
@@ -779,11 +779,6 @@ export interface ZodCustom<O = unknown, I = unknown> extends _ZodType<core.$ZodC
779
779
  "~standard": ZodStandardSchemaWithJSON<this>;
780
780
  }
781
781
  export declare const ZodCustom: core.$constructor<ZodCustom>;
782
- export interface ZodProperties<Shape extends core.$ZodShape = core.$ZodShape> extends _ZodType<core.$ZodPropertiesInternals<Shape>>, core.$ZodProperties<Shape> {
783
- "~standard": ZodStandardSchemaWithJSON<this>;
784
- }
785
- export declare const ZodProperties: core.$constructor<ZodProperties>;
786
- export declare function properties<Shape extends core.$ZodShape>(shape: Shape, params?: string | core.$ZodPropertiesParams): ZodProperties<Shape>;
787
782
  export declare function check<O = unknown>(fn: core.CheckFn<O>): core.$ZodCheck<O>;
788
783
  export declare function custom<O>(fn?: (data: unknown) => unknown, _params?: string | core.$ZodCustomParams | undefined): ZodCustom<O, O>;
789
784
  export declare function refine<T>(fn: (arg: NoInfer<T>) => util.MaybeAsync<unknown>, _params?: string | core.$ZodCustomParams): core.$ZodCheck<T>;
@@ -792,7 +787,7 @@ export declare const describe: typeof core.describe;
792
787
  export declare const meta: typeof core.meta;
793
788
  type ZodInstanceOfParams = core.Params<ZodCustom, core.$ZodIssueCustom, "type" | "check" | "checks" | "fn" | "abort" | "error" | "params" | "path">;
794
789
  export interface ZodInstanceOf<T = unknown> extends ZodCustom<T, T> {
795
- properties<Shape extends core.$ZodShape>(shape: Shape, params?: string | core.$ZodPropertiesParams): ZodInstanceOf<T & core.$InferObjectInput<Shape, {}>>;
790
+ properties<Shape extends core.$ZodShape>(shape: Shape, params?: string | core.$ZodCheckPropertiesParams): ZodInstanceOf<T & core.$InferObjectInput<Shape, {}>>;
796
791
  }
797
792
  export declare const ZodInstanceOf: core.$constructor<ZodInstanceOf>;
798
793
  declare function _instanceof<T extends typeof util.Class>(cls: T, params?: ZodInstanceOfParams): ZodInstanceOf<InstanceType<T>>;
@@ -779,11 +779,6 @@ export interface ZodCustom<O = unknown, I = unknown> extends _ZodType<core.$ZodC
779
779
  "~standard": ZodStandardSchemaWithJSON<this>;
780
780
  }
781
781
  export declare const ZodCustom: core.$constructor<ZodCustom>;
782
- export interface ZodProperties<Shape extends core.$ZodShape = core.$ZodShape> extends _ZodType<core.$ZodPropertiesInternals<Shape>>, core.$ZodProperties<Shape> {
783
- "~standard": ZodStandardSchemaWithJSON<this>;
784
- }
785
- export declare const ZodProperties: core.$constructor<ZodProperties>;
786
- export declare function properties<Shape extends core.$ZodShape>(shape: Shape, params?: string | core.$ZodPropertiesParams): ZodProperties<Shape>;
787
782
  export declare function check<O = unknown>(fn: core.CheckFn<O>): core.$ZodCheck<O>;
788
783
  export declare function custom<O>(fn?: (data: unknown) => unknown, _params?: string | core.$ZodCustomParams | undefined): ZodCustom<O, O>;
789
784
  export declare function refine<T>(fn: (arg: NoInfer<T>) => util.MaybeAsync<unknown>, _params?: string | core.$ZodCustomParams): core.$ZodCheck<T>;
@@ -792,7 +787,7 @@ export declare const describe: typeof core.describe;
792
787
  export declare const meta: typeof core.meta;
793
788
  type ZodInstanceOfParams = core.Params<ZodCustom, core.$ZodIssueCustom, "type" | "check" | "checks" | "fn" | "abort" | "error" | "params" | "path">;
794
789
  export interface ZodInstanceOf<T = unknown> extends ZodCustom<T, T> {
795
- properties<Shape extends core.$ZodShape>(shape: Shape, params?: string | core.$ZodPropertiesParams): ZodInstanceOf<T & core.$InferObjectInput<Shape, {}>>;
790
+ properties<Shape extends core.$ZodShape>(shape: Shape, params?: string | core.$ZodCheckPropertiesParams): ZodInstanceOf<T & core.$InferObjectInput<Shape, {}>>;
796
791
  }
797
792
  export declare const ZodInstanceOf: core.$constructor<ZodInstanceOf>;
798
793
  declare function _instanceof<T extends typeof util.Class>(cls: T, params?: ZodInstanceOfParams): ZodInstanceOf<InstanceType<T>>;
@@ -1455,14 +1455,6 @@ export const ZodCustom = /*@__PURE__*/ core.$constructor("ZodCustom", (inst, def
1455
1455
  ZodType.init(inst, def);
1456
1456
  inst._zod.processJSONSchema = (ctx, json, params) => processors.customProcessor(inst, ctx, json, params);
1457
1457
  });
1458
- export const ZodProperties = /*@__PURE__*/ core.$constructor("ZodProperties", (inst, def) => {
1459
- _ensureDefaultMemoizer();
1460
- core.$ZodProperties.init(inst, def);
1461
- ZodType.init(inst, def);
1462
- });
1463
- export function properties(shape, params) {
1464
- return core._properties(ZodProperties, shape, params);
1465
- }
1466
1458
  // custom checks
1467
1459
  export function check(fn) {
1468
1460
  const ch = new core.$ZodCheck({
@@ -1490,7 +1482,7 @@ export const ZodInstanceOf = /*@__PURE__*/ core.$constructor("ZodInstanceOf", (i
1490
1482
  }, {
1491
1483
  properties(shape, params) {
1492
1484
  // asserts in place, so the narrowed output type is truthful without a wrapper
1493
- return this.check(properties(shape, params));
1485
+ return this.check(core._properties(shape, params));
1494
1486
  },
1495
1487
  });
1496
1488
  function _instanceof(cls, params = {}) {
package/v4/core/api.cjs CHANGED
@@ -831,9 +831,8 @@ function _property(property, schema, params) {
831
831
  });
832
832
  }
833
833
  // @__NO_SIDE_EFFECTS__
834
- function _properties(Class, shape, params) {
835
- return new Class({
836
- type: "properties",
834
+ function _properties(shape, params) {
835
+ return new checks.$ZodCheckProperties({
837
836
  check: "properties",
838
837
  shape,
839
838
  ...util.normalizeParams(params),