zod 4.3.2 → 4.3.4

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zod",
3
- "version": "4.3.2",
3
+ "version": "4.3.4",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "author": "Colin McDonnell <zod@colinhacks.com>",
@@ -597,7 +597,7 @@ function convertSchema(schema: JSONSchema.JSONSchema | boolean, ctx: ConversionC
597
597
  }
598
598
  }
599
599
 
600
- // Content keywords that should be captured as metadata
600
+ // Content keywords - store as metadata
601
601
  const contentMetadataKeys = ["contentEncoding", "contentMediaType", "contentSchema"];
602
602
  for (const key of contentMetadataKeys) {
603
603
  if (key in schema) {
@@ -92,7 +92,7 @@ export interface ZodType<
92
92
  refine<Ch extends (arg: core.output<this>) => unknown | Promise<unknown>>(
93
93
  check: Ch,
94
94
  params?: string | core.$ZodCustomParams
95
- ): Ch extends (arg: any) => arg is infer R ? core.$ZodNarrow<this, R> : this;
95
+ ): Ch extends (arg: any) => arg is infer R ? this & ZodType<R, core.input<this>> : this;
96
96
  superRefine(
97
97
  refinement: (arg: core.output<this>, ctx: core.$RefinementCtx<core.output<this>>) => void | Promise<void>
98
98
  ): this;
@@ -711,3 +711,24 @@ test("$comment and $anchor are captured as metadata", () => {
711
711
  expect(meta?.$comment).toBe("This is a developer note");
712
712
  expect(meta?.$anchor).toBe("my-anchor");
713
713
  });
714
+
715
+ test("contentEncoding and contentMediaType are stored as metadata", () => {
716
+ const customRegistry = z.registry<{ contentEncoding?: string; contentMediaType?: string }>();
717
+
718
+ const schema = fromJSONSchema(
719
+ {
720
+ type: "string",
721
+ contentEncoding: "base64",
722
+ contentMediaType: "image/png",
723
+ },
724
+ { registry: customRegistry }
725
+ );
726
+
727
+ // Should just be a string schema
728
+ expect(schema.parse("aGVsbG8gd29ybGQ=")).toBe("aGVsbG8gd29ybGQ=");
729
+
730
+ // Content keywords should be in metadata
731
+ const meta = customRegistry.get(schema);
732
+ expect(meta?.contentEncoding).toBe("base64");
733
+ expect(meta?.contentMediaType).toBe("image/png");
734
+ });
@@ -524,6 +524,58 @@ test("intersection of loose records", () => {
524
524
  expect(() => schema.parse({ name: "John", N_count: "abc" })).toThrow(); // N_count should be number
525
525
  });
526
526
 
527
+ test("object with looseRecord index signature", () => {
528
+ // Simulates TypeScript index signature: { label: string; [key: `label:${string}`]: string }
529
+ const schema = z.object({ label: z.string() }).and(z.looseRecord(z.string().regex(/^label:[a-z]{2}$/), z.string()));
530
+
531
+ type Schema = z.infer<typeof schema>;
532
+ expectTypeOf<Schema>().toEqualTypeOf<{ label: string } & Record<string, string>>();
533
+
534
+ // Valid: has required property and matching pattern keys
535
+ expect(schema.parse({ label: "Purple", "label:en": "Purple", "label:ru": "Пурпурный" })).toEqual({
536
+ label: "Purple",
537
+ "label:en": "Purple",
538
+ "label:ru": "Пурпурный",
539
+ });
540
+
541
+ // Valid: just required property
542
+ expect(schema.parse({ label: "Purple" })).toEqual({ label: "Purple" });
543
+
544
+ // Invalid: missing required property
545
+ expect(schema.safeParse({ "label:en": "Purple" })).toMatchInlineSnapshot(`
546
+ {
547
+ "error": [ZodError: [
548
+ {
549
+ "expected": "string",
550
+ "code": "invalid_type",
551
+ "path": [
552
+ "label"
553
+ ],
554
+ "message": "Invalid input: expected string, received undefined"
555
+ }
556
+ ]],
557
+ "success": false,
558
+ }
559
+ `);
560
+
561
+ // Invalid: pattern key with wrong value type
562
+ expect(schema.safeParse({ label: "Purple", "label:en": 123 })).toMatchInlineSnapshot(`
563
+ {
564
+ "error": [ZodError: [
565
+ {
566
+ "expected": "string",
567
+ "code": "invalid_type",
568
+ "path": [
569
+ "label:en"
570
+ ],
571
+ "message": "Invalid input: expected string, received number"
572
+ }
573
+ ]],
574
+ "success": false,
575
+ }
576
+ `);
577
+ });
578
+
527
579
  test("numeric string keys", () => {
528
580
  const schema = z.record(z.number(), z.number());
529
581
 
@@ -929,6 +929,117 @@ describe("toJSONSchema", () => {
929
929
  `);
930
930
  });
931
931
 
932
+ test("strict record with regex key uses propertyNames", () => {
933
+ const schema = z.record(z.string().regex(/^label:[a-z]{2}$/), z.string());
934
+
935
+ expect(z.toJSONSchema(schema)).toMatchInlineSnapshot(`
936
+ {
937
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
938
+ "additionalProperties": {
939
+ "type": "string",
940
+ },
941
+ "propertyNames": {
942
+ "pattern": "^label:[a-z]{2}$",
943
+ "type": "string",
944
+ },
945
+ "type": "object",
946
+ }
947
+ `);
948
+ });
949
+
950
+ test("looseRecord with regex key uses patternProperties", () => {
951
+ const schema = z.looseRecord(z.string().regex(/^label:[a-z]{2}$/), z.string());
952
+
953
+ expect(z.toJSONSchema(schema)).toMatchInlineSnapshot(`
954
+ {
955
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
956
+ "patternProperties": {
957
+ "^label:[a-z]{2}$": {
958
+ "type": "string",
959
+ },
960
+ },
961
+ "type": "object",
962
+ }
963
+ `);
964
+ });
965
+
966
+ test("looseRecord with multiple regex patterns uses patternProperties", () => {
967
+ const schema = z.looseRecord(
968
+ z
969
+ .string()
970
+ .regex(/^prefix_/)
971
+ .regex(/_suffix$/),
972
+ z.number()
973
+ );
974
+
975
+ expect(z.toJSONSchema(schema)).toMatchInlineSnapshot(`
976
+ {
977
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
978
+ "patternProperties": {
979
+ "^prefix_": {
980
+ "type": "number",
981
+ },
982
+ "_suffix$": {
983
+ "type": "number",
984
+ },
985
+ },
986
+ "type": "object",
987
+ }
988
+ `);
989
+ });
990
+
991
+ test("looseRecord without regex key uses propertyNames", () => {
992
+ // looseRecord with plain string key should still use propertyNames
993
+ const schema = z.looseRecord(z.string(), z.boolean());
994
+
995
+ expect(z.toJSONSchema(schema)).toMatchInlineSnapshot(`
996
+ {
997
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
998
+ "additionalProperties": {
999
+ "type": "boolean",
1000
+ },
1001
+ "propertyNames": {
1002
+ "type": "string",
1003
+ },
1004
+ "type": "object",
1005
+ }
1006
+ `);
1007
+ });
1008
+
1009
+ test("intersection of object with looseRecord uses patternProperties", () => {
1010
+ const zLabeled = z.object({ label: z.string() });
1011
+ const zLocalizedLabeled = z.looseRecord(z.string().regex(/^label:[a-z]{2}$/), z.string());
1012
+ const schema = zLabeled.and(zLocalizedLabeled);
1013
+
1014
+ expect(z.toJSONSchema(schema)).toMatchInlineSnapshot(`
1015
+ {
1016
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
1017
+ "allOf": [
1018
+ {
1019
+ "additionalProperties": false,
1020
+ "properties": {
1021
+ "label": {
1022
+ "type": "string",
1023
+ },
1024
+ },
1025
+ "required": [
1026
+ "label",
1027
+ ],
1028
+ "type": "object",
1029
+ },
1030
+ {
1031
+ "patternProperties": {
1032
+ "^label:[a-z]{2}$": {
1033
+ "type": "string",
1034
+ },
1035
+ },
1036
+ "type": "object",
1037
+ },
1038
+ ],
1039
+ }
1040
+ `);
1041
+ });
1042
+
932
1043
  test("tuple", () => {
933
1044
  const schema = z.tuple([z.string(), z.number()]);
934
1045
  expect(z.toJSONSchema(schema)).toMatchInlineSnapshot(`
@@ -431,26 +431,47 @@ export const recordProcessor: Processor<schemas.$ZodRecord> = (schema, ctx, _jso
431
431
  const json = _json as JSONSchema.ObjectSchema;
432
432
  const def = schema._zod.def as schemas.$ZodRecordDef;
433
433
  json.type = "object";
434
- if (ctx.target === "draft-07" || ctx.target === "draft-2020-12") {
435
- json.propertyNames = process(def.keyType, ctx as any, {
434
+
435
+ // For looseRecord with regex patterns, use patternProperties
436
+ // This correctly represents "only validate keys matching the pattern" semantics
437
+ // and composes well with allOf (intersections)
438
+ const keyType = def.keyType as schemas.$ZodTypes;
439
+ const keyBag = keyType._zod.bag as schemas.$ZodStringInternals<unknown>["bag"] | undefined;
440
+ const patterns = keyBag?.patterns;
441
+
442
+ if (def.mode === "loose" && patterns && patterns.size > 0) {
443
+ // Use patternProperties for looseRecord with regex patterns
444
+ const valueSchema = process(def.valueType, ctx as any, {
436
445
  ...params,
437
- path: [...params.path, "propertyNames"],
446
+ path: [...params.path, "patternProperties", "*"],
447
+ });
448
+ json.patternProperties = {};
449
+ for (const pattern of patterns) {
450
+ json.patternProperties[pattern.source] = valueSchema;
451
+ }
452
+ } else {
453
+ // Default behavior: use propertyNames + additionalProperties
454
+ if (ctx.target === "draft-07" || ctx.target === "draft-2020-12") {
455
+ json.propertyNames = process(def.keyType, ctx as any, {
456
+ ...params,
457
+ path: [...params.path, "propertyNames"],
458
+ });
459
+ }
460
+ json.additionalProperties = process(def.valueType, ctx as any, {
461
+ ...params,
462
+ path: [...params.path, "additionalProperties"],
438
463
  });
439
464
  }
440
- json.additionalProperties = process(def.valueType, ctx as any, {
441
- ...params,
442
- path: [...params.path, "additionalProperties"],
443
- });
444
465
 
445
- const keyDef = (def.keyType as schemas.$ZodTypes)._zod.def;
446
- if (keyDef.type === "enum") {
447
- const enumValues = getEnumValues(keyDef.entries);
448
- const validEnumValues = enumValues.filter(
466
+ // Add required for keys with discrete values (enum, literal, etc.)
467
+ const keyValues = keyType._zod.values;
468
+ if (keyValues) {
469
+ const validKeyValues = [...keyValues].filter(
449
470
  (v): v is string | number => typeof v === "string" || typeof v === "number"
450
471
  );
451
472
 
452
- if (validEnumValues.length > 0) {
453
- json.required = validEnumValues as string[];
473
+ if (validKeyValues.length > 0) {
474
+ json.required = validKeyValues as string[];
454
475
  }
455
476
  }
456
477
  };
@@ -1,5 +1,5 @@
1
1
  export const version = {
2
2
  major: 4,
3
3
  minor: 3,
4
- patch: 2 as number,
4
+ patch: 4 as number,
5
5
  } as const;
@@ -12,10 +12,6 @@ export interface ZodMiniType<
12
12
  type: Internals["def"]["type"];
13
13
  check(...checks: (core.CheckFn<core.output<this>> | core.$ZodCheck<core.output<this>>)[]): this;
14
14
  with(...checks: (core.CheckFn<core.output<this>> | core.$ZodCheck<core.output<this>>)[]): this;
15
- refine<Ch extends (arg: core.output<this>) => unknown | Promise<unknown>>(
16
- check: Ch,
17
- params?: string | core.$ZodCustomParams
18
- ): Ch extends (arg: any) => arg is infer R ? core.$ZodNarrow<this, R> : this;
19
15
  clone(def?: Internals["def"], params?: { parent: boolean }): this;
20
16
  register<R extends core.$ZodRegistry>(
21
17
  registry: R,
@@ -72,7 +68,6 @@ export const ZodMiniType: core.$constructor<ZodMiniType> = /*@__PURE__*/ core.$c
72
68
  );
73
69
  };
74
70
  inst.with = inst.check;
75
- inst.refine = (check, params) => inst.check(refine(check, params)) as never;
76
71
  inst.clone = (_def, params) => core.clone(inst, _def, params);
77
72
  inst.brand = () => inst as any;
78
73
  inst.register = ((reg: any, meta: any) => {
@@ -571,7 +571,7 @@ function convertSchema(schema, ctx) {
571
571
  extraMeta[key] = schema[key];
572
572
  }
573
573
  }
574
- // Content keywords that should be captured as metadata
574
+ // Content keywords - store as metadata
575
575
  const contentMetadataKeys = ["contentEncoding", "contentMediaType", "contentSchema"];
576
576
  for (const key of contentMetadataKeys) {
577
577
  if (key in schema) {
@@ -545,7 +545,7 @@ function convertSchema(schema, ctx) {
545
545
  extraMeta[key] = schema[key];
546
546
  }
547
547
  }
548
- // Content keywords that should be captured as metadata
548
+ // Content keywords - store as metadata
549
549
  const contentMetadataKeys = ["contentEncoding", "contentMediaType", "contentSchema"];
550
550
  for (const key of contentMetadataKeys) {
551
551
  if (key in schema) {
@@ -35,7 +35,7 @@ export interface ZodType<out Output = unknown, out Input = unknown, out Internal
35
35
  safeDecode(data: core.input<this>, params?: core.ParseContext<core.$ZodIssue>): parse.ZodSafeParseResult<core.output<this>>;
36
36
  safeEncodeAsync(data: core.output<this>, params?: core.ParseContext<core.$ZodIssue>): Promise<parse.ZodSafeParseResult<core.input<this>>>;
37
37
  safeDecodeAsync(data: core.input<this>, params?: core.ParseContext<core.$ZodIssue>): Promise<parse.ZodSafeParseResult<core.output<this>>>;
38
- refine<Ch extends (arg: core.output<this>) => unknown | Promise<unknown>>(check: Ch, params?: string | core.$ZodCustomParams): Ch extends (arg: any) => arg is infer R ? core.$ZodNarrow<this, R> : this;
38
+ refine<Ch extends (arg: core.output<this>) => unknown | Promise<unknown>>(check: Ch, params?: string | core.$ZodCustomParams): Ch extends (arg: any) => arg is infer R ? this & ZodType<R, core.input<this>> : this;
39
39
  superRefine(refinement: (arg: core.output<this>, ctx: core.$RefinementCtx<core.output<this>>) => void | Promise<void>): this;
40
40
  overwrite(fn: (x: core.output<this>) => core.output<this>): this;
41
41
  optional(): ZodOptional<this>;
@@ -35,7 +35,7 @@ export interface ZodType<out Output = unknown, out Input = unknown, out Internal
35
35
  safeDecode(data: core.input<this>, params?: core.ParseContext<core.$ZodIssue>): parse.ZodSafeParseResult<core.output<this>>;
36
36
  safeEncodeAsync(data: core.output<this>, params?: core.ParseContext<core.$ZodIssue>): Promise<parse.ZodSafeParseResult<core.input<this>>>;
37
37
  safeDecodeAsync(data: core.input<this>, params?: core.ParseContext<core.$ZodIssue>): Promise<parse.ZodSafeParseResult<core.output<this>>>;
38
- refine<Ch extends (arg: core.output<this>) => unknown | Promise<unknown>>(check: Ch, params?: string | core.$ZodCustomParams): Ch extends (arg: any) => arg is infer R ? core.$ZodNarrow<this, R> : this;
38
+ refine<Ch extends (arg: core.output<this>) => unknown | Promise<unknown>>(check: Ch, params?: string | core.$ZodCustomParams): Ch extends (arg: any) => arg is infer R ? this & ZodType<R, core.input<this>> : this;
39
39
  superRefine(refinement: (arg: core.output<this>, ctx: core.$RefinementCtx<core.output<this>>) => void | Promise<void>): this;
40
40
  overwrite(fn: (x: core.output<this>) => core.output<this>): this;
41
41
  optional(): ZodOptional<this>;
@@ -436,22 +436,42 @@ const recordProcessor = (schema, ctx, _json, params) => {
436
436
  const json = _json;
437
437
  const def = schema._zod.def;
438
438
  json.type = "object";
439
- if (ctx.target === "draft-07" || ctx.target === "draft-2020-12") {
440
- json.propertyNames = (0, to_json_schema_js_1.process)(def.keyType, ctx, {
439
+ // For looseRecord with regex patterns, use patternProperties
440
+ // This correctly represents "only validate keys matching the pattern" semantics
441
+ // and composes well with allOf (intersections)
442
+ const keyType = def.keyType;
443
+ const keyBag = keyType._zod.bag;
444
+ const patterns = keyBag?.patterns;
445
+ if (def.mode === "loose" && patterns && patterns.size > 0) {
446
+ // Use patternProperties for looseRecord with regex patterns
447
+ const valueSchema = (0, to_json_schema_js_1.process)(def.valueType, ctx, {
441
448
  ...params,
442
- path: [...params.path, "propertyNames"],
449
+ path: [...params.path, "patternProperties", "*"],
443
450
  });
451
+ json.patternProperties = {};
452
+ for (const pattern of patterns) {
453
+ json.patternProperties[pattern.source] = valueSchema;
454
+ }
444
455
  }
445
- json.additionalProperties = (0, to_json_schema_js_1.process)(def.valueType, ctx, {
446
- ...params,
447
- path: [...params.path, "additionalProperties"],
448
- });
449
- const keyDef = def.keyType._zod.def;
450
- if (keyDef.type === "enum") {
451
- const enumValues = (0, util_js_1.getEnumValues)(keyDef.entries);
452
- const validEnumValues = enumValues.filter((v) => typeof v === "string" || typeof v === "number");
453
- if (validEnumValues.length > 0) {
454
- json.required = validEnumValues;
456
+ else {
457
+ // Default behavior: use propertyNames + additionalProperties
458
+ if (ctx.target === "draft-07" || ctx.target === "draft-2020-12") {
459
+ json.propertyNames = (0, to_json_schema_js_1.process)(def.keyType, ctx, {
460
+ ...params,
461
+ path: [...params.path, "propertyNames"],
462
+ });
463
+ }
464
+ json.additionalProperties = (0, to_json_schema_js_1.process)(def.valueType, ctx, {
465
+ ...params,
466
+ path: [...params.path, "additionalProperties"],
467
+ });
468
+ }
469
+ // Add required for keys with discrete values (enum, literal, etc.)
470
+ const keyValues = keyType._zod.values;
471
+ if (keyValues) {
472
+ const validKeyValues = [...keyValues].filter((v) => typeof v === "string" || typeof v === "number");
473
+ if (validKeyValues.length > 0) {
474
+ json.required = validKeyValues;
455
475
  }
456
476
  }
457
477
  };
@@ -404,22 +404,42 @@ export const recordProcessor = (schema, ctx, _json, params) => {
404
404
  const json = _json;
405
405
  const def = schema._zod.def;
406
406
  json.type = "object";
407
- if (ctx.target === "draft-07" || ctx.target === "draft-2020-12") {
408
- json.propertyNames = process(def.keyType, ctx, {
407
+ // For looseRecord with regex patterns, use patternProperties
408
+ // This correctly represents "only validate keys matching the pattern" semantics
409
+ // and composes well with allOf (intersections)
410
+ const keyType = def.keyType;
411
+ const keyBag = keyType._zod.bag;
412
+ const patterns = keyBag?.patterns;
413
+ if (def.mode === "loose" && patterns && patterns.size > 0) {
414
+ // Use patternProperties for looseRecord with regex patterns
415
+ const valueSchema = process(def.valueType, ctx, {
409
416
  ...params,
410
- path: [...params.path, "propertyNames"],
417
+ path: [...params.path, "patternProperties", "*"],
411
418
  });
419
+ json.patternProperties = {};
420
+ for (const pattern of patterns) {
421
+ json.patternProperties[pattern.source] = valueSchema;
422
+ }
412
423
  }
413
- json.additionalProperties = process(def.valueType, ctx, {
414
- ...params,
415
- path: [...params.path, "additionalProperties"],
416
- });
417
- const keyDef = def.keyType._zod.def;
418
- if (keyDef.type === "enum") {
419
- const enumValues = getEnumValues(keyDef.entries);
420
- const validEnumValues = enumValues.filter((v) => typeof v === "string" || typeof v === "number");
421
- if (validEnumValues.length > 0) {
422
- json.required = validEnumValues;
424
+ else {
425
+ // Default behavior: use propertyNames + additionalProperties
426
+ if (ctx.target === "draft-07" || ctx.target === "draft-2020-12") {
427
+ json.propertyNames = process(def.keyType, ctx, {
428
+ ...params,
429
+ path: [...params.path, "propertyNames"],
430
+ });
431
+ }
432
+ json.additionalProperties = process(def.valueType, ctx, {
433
+ ...params,
434
+ path: [...params.path, "additionalProperties"],
435
+ });
436
+ }
437
+ // Add required for keys with discrete values (enum, literal, etc.)
438
+ const keyValues = keyType._zod.values;
439
+ if (keyValues) {
440
+ const validKeyValues = [...keyValues].filter((v) => typeof v === "string" || typeof v === "number");
441
+ if (validKeyValues.length > 0) {
442
+ json.required = validKeyValues;
423
443
  }
424
444
  }
425
445
  };
@@ -4,5 +4,5 @@ exports.version = void 0;
4
4
  exports.version = {
5
5
  major: 4,
6
6
  minor: 3,
7
- patch: 2,
7
+ patch: 4,
8
8
  };
@@ -1,5 +1,5 @@
1
1
  export const version = {
2
2
  major: 4,
3
3
  minor: 3,
4
- patch: 2,
4
+ patch: 4,
5
5
  };
@@ -149,7 +149,6 @@ exports.ZodMiniType = core.$constructor("ZodMiniType", (inst, def) => {
149
149
  }, { parent: true });
150
150
  };
151
151
  inst.with = inst.check;
152
- inst.refine = (check, params) => inst.check(refine(check, params));
153
152
  inst.clone = (_def, params) => core.clone(inst, _def, params);
154
153
  inst.brand = () => inst;
155
154
  inst.register = ((reg, meta) => {
@@ -5,7 +5,6 @@ export interface ZodMiniType<out Output = unknown, out Input = unknown, out Inte
5
5
  type: Internals["def"]["type"];
6
6
  check(...checks: (core.CheckFn<core.output<this>> | core.$ZodCheck<core.output<this>>)[]): this;
7
7
  with(...checks: (core.CheckFn<core.output<this>> | core.$ZodCheck<core.output<this>>)[]): this;
8
- refine<Ch extends (arg: core.output<this>) => unknown | Promise<unknown>>(check: Ch, params?: string | core.$ZodCustomParams): Ch extends (arg: any) => arg is infer R ? core.$ZodNarrow<this, R> : this;
9
8
  clone(def?: Internals["def"], params?: {
10
9
  parent: boolean;
11
10
  }): this;
@@ -5,7 +5,6 @@ export interface ZodMiniType<out Output = unknown, out Input = unknown, out Inte
5
5
  type: Internals["def"]["type"];
6
6
  check(...checks: (core.CheckFn<core.output<this>> | core.$ZodCheck<core.output<this>>)[]): this;
7
7
  with(...checks: (core.CheckFn<core.output<this>> | core.$ZodCheck<core.output<this>>)[]): this;
8
- refine<Ch extends (arg: core.output<this>) => unknown | Promise<unknown>>(check: Ch, params?: string | core.$ZodCustomParams): Ch extends (arg: any) => arg is infer R ? core.$ZodNarrow<this, R> : this;
9
8
  clone(def?: Internals["def"], params?: {
10
9
  parent: boolean;
11
10
  }): this;
@@ -21,7 +21,6 @@ export const ZodMiniType = /*@__PURE__*/ core.$constructor("ZodMiniType", (inst,
21
21
  }, { parent: true });
22
22
  };
23
23
  inst.with = inst.check;
24
- inst.refine = (check, params) => inst.check(refine(check, params));
25
24
  inst.clone = (_def, params) => core.clone(inst, _def, params);
26
25
  inst.brand = () => inst;
27
26
  inst.register = ((reg, meta) => {
@@ -1,19 +0,0 @@
1
- import { describe, expectTypeOf, test } from "vitest";
2
- import type * as core from "../../core/index.js";
3
- import * as z from "../index.js";
4
-
5
- describe("type refinement with type guards", () => {
6
- test("type guard narrows output type", () => {
7
- const schema = z.string().refine((s): s is "a" => s === "a");
8
-
9
- expectTypeOf<core.input<typeof schema>>().toEqualTypeOf<string>();
10
- expectTypeOf<core.output<typeof schema>>().toEqualTypeOf<"a">();
11
- });
12
-
13
- test("non-type-guard refine does not narrow", () => {
14
- const schema = z.string().refine((s) => s.length > 0);
15
-
16
- expectTypeOf<core.input<typeof schema>>().toEqualTypeOf<string>();
17
- expectTypeOf<core.output<typeof schema>>().toEqualTypeOf<string>();
18
- });
19
- });