zod 3.26.0-canary.20250703T214020 → 3.26.0-canary.20250707T201657
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.
- package/index.cjs +2 -2
- package/index.d.cts +2 -2
- package/index.d.ts +2 -2
- package/index.js +2 -2
- package/package.json +1 -1
- package/src/index.ts +2 -2
- package/src/v4/classic/schemas.ts +4 -2
- package/src/v4/classic/tests/brand.test.ts +1 -3
- package/src/v4/classic/tests/discriminated-unions.test.ts +27 -0
- package/src/v4/classic/tests/index.test.ts +1 -1
- package/src/v4/classic/tests/object.test.ts +11 -1
- package/src/v4/classic/tests/optional.test.ts +20 -0
- package/src/v4/classic/tests/record.test.ts +11 -1
- package/src/v4/classic/tests/recursive-types.test.ts +3 -2
- package/src/v4/classic/tests/to-json-schema.test.ts +95 -2
- package/src/v4/core/registries.ts +4 -0
- package/src/v4/core/schemas.ts +93 -32
- package/src/v4/core/to-json-schema.ts +23 -11
- package/src/v4/mini/schemas.ts +2 -2
- package/src/v4/mini/tests/string.test.ts +6 -0
- package/v4/classic/schemas.d.cts +2 -1
- package/v4/classic/schemas.d.ts +2 -1
- package/v4/core/registries.cjs +4 -0
- package/v4/core/registries.js +4 -0
- package/v4/core/schemas.cjs +18 -5
- package/v4/core/schemas.d.cts +35 -9
- package/v4/core/schemas.d.ts +35 -9
- package/v4/core/schemas.js +18 -5
- package/v4/core/to-json-schema.cjs +10 -8
- package/v4/core/to-json-schema.d.cts +5 -1
- package/v4/core/to-json-schema.d.ts +5 -1
- package/v4/core/to-json-schema.js +10 -8
- package/v4/mini/schemas.d.cts +1 -1
- package/v4/mini/schemas.d.ts +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/
|
|
30
|
+
const z = __importStar(require("./v3/external.cjs"));
|
|
31
31
|
exports.z = z;
|
|
32
|
-
__exportStar(require("./v3/
|
|
32
|
+
__exportStar(require("./v3/external.cjs"), exports);
|
|
33
33
|
exports.default = z;
|
package/index.d.cts
CHANGED
package/index.d.ts
CHANGED
package/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "zod",
|
|
3
|
-
"version": "3.26.0-canary.
|
|
3
|
+
"version": "3.26.0-canary.20250707T201657",
|
|
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
|
@@ -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<
|
|
1362
|
+
): ZodRecord<Key & core.$partial, Value> {
|
|
1361
1363
|
return new ZodRecord({
|
|
1362
1364
|
type: "record",
|
|
1363
1365
|
keyType: union([keyType, never()]),
|
|
1364
|
-
valueType: valueType as any
|
|
1366
|
+
valueType: valueType as any,
|
|
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<
|
|
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,
|
|
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<
|
|
20
|
+
expectTypeOf<recordWithLiteralUnionKeys>().toEqualTypeOf<Record<"Tuna" | "Salmon", string>>();
|
|
21
21
|
});
|
|
22
22
|
|
|
23
23
|
test("enum exhaustiveness", () => {
|
|
@@ -330,3 +330,13 @@ 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
|
+
|
|
339
|
+
const Keys = z.enum(["id", "name", "email"]).or(z.never());
|
|
340
|
+
const Person = z.partialRecord(Keys, z.string());
|
|
341
|
+
expectTypeOf<z.infer<typeof Person>>().toEqualTypeOf<Partial<Record<"id" | "name" | "email", string>>>();
|
|
342
|
+
});
|
|
@@ -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.
|
|
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 = {
|
|
@@ -28,10 +28,9 @@ describe("toJSONSchema", () => {
|
|
|
28
28
|
"type": "null",
|
|
29
29
|
}
|
|
30
30
|
`);
|
|
31
|
-
expect(z.toJSONSchema(z.undefined())).toMatchInlineSnapshot(`
|
|
31
|
+
expect(z.toJSONSchema(z.undefined(), { unrepresentable: "any" })).toMatchInlineSnapshot(`
|
|
32
32
|
{
|
|
33
33
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
34
|
-
"type": "null",
|
|
35
34
|
}
|
|
36
35
|
`);
|
|
37
36
|
expect(z.toJSONSchema(z.any())).toMatchInlineSnapshot(`
|
|
@@ -232,6 +231,7 @@ describe("toJSONSchema", () => {
|
|
|
232
231
|
expect(() => z.toJSONSchema(z.int64())).toThrow("BigInt cannot be represented in JSON Schema");
|
|
233
232
|
expect(() => z.toJSONSchema(z.symbol())).toThrow("Symbols cannot be represented in JSON Schema");
|
|
234
233
|
expect(() => z.toJSONSchema(z.void())).toThrow("Void cannot be represented in JSON Schema");
|
|
234
|
+
expect(() => z.toJSONSchema(z.undefined())).toThrow("Undefined cannot be represented in JSON Schema");
|
|
235
235
|
expect(() => z.toJSONSchema(z.date())).toThrow("Date cannot be represented in JSON Schema");
|
|
236
236
|
expect(() => z.toJSONSchema(z.map(z.string(), z.number()))).toThrow("Map cannot be represented in JSON Schema");
|
|
237
237
|
expect(() => z.toJSONSchema(z.set(z.string()))).toThrow("Set cannot be represented in JSON Schema");
|
|
@@ -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,10 @@ 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.union([z.string(), z.number().default(2)]),
|
|
1891
|
+
i: z.union([z.string(), z.string().optional()]),
|
|
1859
1892
|
});
|
|
1860
1893
|
expect(z.toJSONSchema(schema, { io: "input" })).toMatchInlineSnapshot(`
|
|
1861
1894
|
{
|
|
@@ -1885,10 +1918,39 @@ test("input type", () => {
|
|
|
1885
1918
|
"default": "hello",
|
|
1886
1919
|
"type": "string",
|
|
1887
1920
|
},
|
|
1921
|
+
"f": {
|
|
1922
|
+
"default": "hello",
|
|
1923
|
+
"type": "string",
|
|
1924
|
+
},
|
|
1925
|
+
"g": {
|
|
1926
|
+
"not": {},
|
|
1927
|
+
},
|
|
1928
|
+
"h": {
|
|
1929
|
+
"anyOf": [
|
|
1930
|
+
{
|
|
1931
|
+
"type": "string",
|
|
1932
|
+
},
|
|
1933
|
+
{
|
|
1934
|
+
"default": 2,
|
|
1935
|
+
"type": "number",
|
|
1936
|
+
},
|
|
1937
|
+
],
|
|
1938
|
+
},
|
|
1939
|
+
"i": {
|
|
1940
|
+
"anyOf": [
|
|
1941
|
+
{
|
|
1942
|
+
"type": "string",
|
|
1943
|
+
},
|
|
1944
|
+
{
|
|
1945
|
+
"type": "string",
|
|
1946
|
+
},
|
|
1947
|
+
],
|
|
1948
|
+
},
|
|
1888
1949
|
},
|
|
1889
1950
|
"required": [
|
|
1890
1951
|
"a",
|
|
1891
1952
|
"d",
|
|
1953
|
+
"g",
|
|
1892
1954
|
],
|
|
1893
1955
|
"type": "object",
|
|
1894
1956
|
}
|
|
@@ -1921,12 +1983,43 @@ test("input type", () => {
|
|
|
1921
1983
|
"e": {
|
|
1922
1984
|
"type": "string",
|
|
1923
1985
|
},
|
|
1986
|
+
"f": {
|
|
1987
|
+
"default": "hello",
|
|
1988
|
+
"type": "string",
|
|
1989
|
+
},
|
|
1990
|
+
"g": {
|
|
1991
|
+
"not": {},
|
|
1992
|
+
},
|
|
1993
|
+
"h": {
|
|
1994
|
+
"anyOf": [
|
|
1995
|
+
{
|
|
1996
|
+
"type": "string",
|
|
1997
|
+
},
|
|
1998
|
+
{
|
|
1999
|
+
"default": 2,
|
|
2000
|
+
"type": "number",
|
|
2001
|
+
},
|
|
2002
|
+
],
|
|
2003
|
+
},
|
|
2004
|
+
"i": {
|
|
2005
|
+
"anyOf": [
|
|
2006
|
+
{
|
|
2007
|
+
"type": "string",
|
|
2008
|
+
},
|
|
2009
|
+
{
|
|
2010
|
+
"type": "string",
|
|
2011
|
+
},
|
|
2012
|
+
],
|
|
2013
|
+
},
|
|
1924
2014
|
},
|
|
1925
2015
|
"required": [
|
|
1926
2016
|
"a",
|
|
1927
2017
|
"c",
|
|
1928
2018
|
"d",
|
|
1929
2019
|
"e",
|
|
2020
|
+
"f",
|
|
2021
|
+
"g",
|
|
2022
|
+
"h",
|
|
1930
2023
|
],
|
|
1931
2024
|
"type": "object",
|
|
1932
2025
|
}
|
|
@@ -46,6 +46,10 @@ export class $ZodRegistry<Meta extends MetadataType = MetadataType, Schema exten
|
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
remove(schema: Schema): this {
|
|
49
|
+
const meta: any = this._map.get(schema);
|
|
50
|
+
if (meta && typeof meta === "object" && "id" in meta) {
|
|
51
|
+
this._idmap.delete(meta.id!);
|
|
52
|
+
}
|
|
49
53
|
this._map.delete(schema);
|
|
50
54
|
return this;
|
|
51
55
|
}
|