zod-compare 0.1.1

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/README.md ADDED
@@ -0,0 +1,98 @@
1
+ # Zod Compare
2
+
3
+ [![Build](https://github.com/lawvs/zod-compare/actions/workflows/build.yml/badge.svg)](https://github.com/lawvs/zod-compare/actions/workflows/build.yml)
4
+
5
+ Compare two [Zod](https://zod.dev/) schemas recursively.
6
+
7
+ `zod-compare` provides functions to compare Zod schemas, allowing you to determine whether two schemas are the same or compatible.
8
+
9
+ ## Installation
10
+
11
+ ```bash
12
+ npm install zod zod-compare --save
13
+ ```
14
+
15
+ ## Usage
16
+
17
+ ```ts
18
+ import { z } from "zod";
19
+ import { isSameType, isCompatibleType } from "zod-compare";
20
+
21
+ isSameType(z.string(), z.string()); // true
22
+ isSameType(z.string(), z.number()); // false
23
+ isSameType(
24
+ z.object({ name: z.string(), other: z.number() }),
25
+ z.object({ name: z.string() }),
26
+ );
27
+ // false
28
+
29
+ isCompatibleType(
30
+ z.object({ name: z.string(), other: z.number() }),
31
+ z.object({ name: z.string() }),
32
+ );
33
+ // true
34
+ ```
35
+
36
+ ## Advanced Usage
37
+
38
+ `isSameType` also offers an `interceptor` option, enabling you to tailor the comparison process according to your needs.
39
+
40
+ ```ts
41
+ isSameType(
42
+ z.object({ name: z.string(), other: z.number() }),
43
+ z.object({ name: z.string() }),
44
+ {
45
+ interceptor: (a, b) => {
46
+ if (a instanceof z.ZodObject && b instanceof z.ZodObject) {
47
+ // return boolean to override the comparison result
48
+ return a.shape.name === b.shape.name;
49
+ }
50
+ // return other values to use the default comparison
51
+ },
52
+ },
53
+ );
54
+ // true
55
+ ```
56
+
57
+ ## Caveats
58
+
59
+ `zod-compare` is designed to compare Zod schemas created by the developer.
60
+ We do not have plans to support comparing schemas that include custom validation functions or other advanced Zod features.
61
+
62
+ This tool will disregard any custom validations like `min`, `max`, `length`, among others.
63
+
64
+ Furthermore, it cannot be utilized for comparing `ZodLazy`, `ZodEffects`, `ZodDefault`, `ZodCatch`, `ZodPipeline`, `ZodTransformer`, `ZodError` types.
65
+
66
+ But you can use the `interceptor` option to customize the comparison process.
67
+
68
+ ## API
69
+
70
+ ### `isSameType`
71
+
72
+ Compares two Zod schemas and returns `true` if they are the same.
73
+
74
+ ```ts
75
+ function isSameType(
76
+ a: ZodType,
77
+ b: ZodType,
78
+ options?: {
79
+ interceptor?: (a: ZodType, b: ZodType) => boolean | undefined;
80
+ },
81
+ ): boolean;
82
+ ```
83
+
84
+ ### `isCompatibleType` (Unstable API)
85
+
86
+ ```ts
87
+ function isCompatibleType(
88
+ a: ZodType,
89
+ b: ZodType,
90
+ options?: {
91
+ interceptor?: (a: ZodType, b: ZodType) => boolean | undefined;
92
+ },
93
+ ): boolean;
94
+ ```
95
+
96
+ ## License
97
+
98
+ MIT
package/dist/index.cjs ADDED
@@ -0,0 +1,2 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("zod"),a={deep:!0,ignoreOptional:!1,ignoreNullable:!1,ignoreReadOnly:!1,ignoreBranded:!1,ignoreValidations:!0,ignoreIntersectionsOrder:!1,interceptor:()=>{}},l=e=>e instanceof t.z.ZodString||e instanceof t.z.ZodNumber||e instanceof t.z.ZodNaN||e instanceof t.z.ZodBigInt||e instanceof t.z.ZodBoolean||e instanceof t.z.ZodDate||e instanceof t.z.ZodSymbol||e instanceof t.z.ZodUndefined||e instanceof t.z.ZodNull||e instanceof t.z.ZodAny||e instanceof t.z.ZodUnknown||e instanceof t.z.ZodNever||e instanceof t.z.ZodVoid,f=(e,n,d)=>{const r={...a,...d},u=r.interceptor(e,n,r);if(u===!0||u===!1)return u;if(e===void 0||n===void 0)throw new Error("Failed to compare type! "+e+" "+n);if(e===n)return!0;if(e.constructor!==n.constructor)return!1;if(!("typeName"in e._def)||!("typeName"in n._def))throw new Error("Failed to compare type! "+e._def+" "+n._def);if(e._def.typeName!==n._def.typeName)return!1;if(r.ignoreBranded)return e instanceof t.z.ZodBranded&&(e=e.unwrap()),n instanceof t.z.ZodBranded&&(n=n.unwrap()),f(e,n,r);if(e instanceof t.z.ZodBranded||n instanceof t.z.ZodBranded)return!1;if("unwrap"in e&&typeof e.unwrap=="function")return"unwrap"in n&&typeof n.unwrap=="function"?f(e.unwrap(),n.unwrap(),r):!1;if(!r.ignoreOptional&&e.isOptional()!==n.isOptional()||!r.ignoreNullable&&e.isNullable()!==n.isNullable())return!1;if(l(e))return!0;if(e instanceof t.z.ZodObject&&n instanceof t.z.ZodObject){const o=e.shape,s=n.shape;if(Object.keys(o).length!==Object.keys(s).length)return!1;for(const i in o)if(!(i in s)||!f(o[i],s[i],r))return!1;return!0}if(e instanceof t.z.ZodArray&&n instanceof t.z.ZodArray)return f(e.element,n.element,r);if(e instanceof t.z.ZodTuple&&n instanceof t.z.ZodTuple){if(e.items.length!==n.items.length)return!1;for(let o=0;o<e.items.length;o++)if(!f(e.items[o],n.items[o],r))return!1;return e._def.rest||n._def.rest?!e._def.rest||!n._def.rest?!1:f(e._def.rest,n._def.rest,r):!0}if(e instanceof t.z.ZodLiteral&&n instanceof t.z.ZodLiteral)return e.value===n.value;if(e instanceof t.z.ZodIntersection&&n instanceof t.z.ZodIntersection)return f(e._def.left,n._def.left,r)&&f(e._def.right,n._def.right,r);if(e instanceof t.z.ZodUnion&&n instanceof t.z.ZodUnion){if(e.options.length!==n.options.length)return!1;for(let o=0;o<e.options.length;o++)if(!f(e.options[o],n.options[o],r))return!1;return!0}if(e instanceof t.z.ZodReadonly&&n instanceof t.z.ZodReadonly)return f(e._def.innerType,n._def.innerType,r);if(e instanceof t.z.ZodRecord&&n instanceof t.z.ZodRecord||e instanceof t.z.ZodMap&&n instanceof t.z.ZodMap)return f(e.keySchema,n.keySchema,r)&&f(e.valueSchema,n.valueSchema,r);if(e instanceof t.z.ZodSet&&n instanceof t.z.ZodSet)return f(e._def.valueType,n._def.valueType,r);if(e instanceof t.z.ZodFunction&&n instanceof t.z.ZodFunction)return f(e.parameters(),n.parameters(),r)&&f(e.returnType(),n.returnType(),r);if(e instanceof t.z.ZodEnum&&n instanceof t.z.ZodEnum){const o=e.options,s=n.options;if(o.length!==s.length)return!1;for(let i=0;i<o.length;i++)if(o[i]!==s[i])return!1;return!0}if(e instanceof t.z.ZodNativeEnum&&n instanceof t.z.ZodNativeEnum){const o=e.enum,s=n.enum;if(Object.keys(o).length!==Object.keys(s).length)return!1;for(const i in o)if(o[i]!==s[i])return!1;return!0}throw console.error('Failed to compare type! "'+e,n),new Error("Unknown type! "+e._def.typeName+" "+n._def.typeName)},c=(e,n,d)=>{const r={...a,...d},u=r.interceptor(e,n,r);if(u===!0||u===!1)return u;if(f(e,n,r))return!0;if(!("typeName"in e._def)||!("typeName"in n._def))throw new Error("Failed to compare type! "+e._def+" "+n._def);if(n instanceof t.z.ZodOptional||n instanceof t.z.ZodNullable)return c(e,n.unwrap(),r);if(e instanceof t.z.ZodUnion&&n instanceof t.z.ZodUnion){for(let o=0;o<e.options.length;o++)if(!n.options.some(i=>c(i,n.options[o],r)))return!1;return!0}if(e instanceof t.z.ZodUnion)return e.options.every(o=>c(o,n,r));if(n instanceof t.z.ZodUnion)return n.options.some(o=>c(e,o,r));if(e.constructor!==n.constructor)return!1;if(e instanceof t.z.ZodObject&&n instanceof t.z.ZodObject){const o=e.shape,s=n.shape;if(Object.keys(o).length<Object.keys(s).length)return!1;for(const i in s)if(!(i in o)||!c(o[i],s[i],r))return!1;return!0}if(e instanceof t.z.ZodArray&&n instanceof t.z.ZodArray)return c(e.element,n.element,r);if(e instanceof t.z.ZodTuple&&n instanceof t.z.ZodTuple){if(e.items.length<n.items.length)return!1;for(let o=0;o<n.items.length;o++)if(!c(e.items[o],n.items[o],r))return!1;return n._def.rest?e._def.rest?c(e._def.rest,n._def.rest,r):!1:!0}throw new Error("Failed to compare types!"+e._def.typeName+" "+n._def.typeName)};exports.isCompatibleType=c;exports.isSameType=f;
2
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs","sources":["../src/utils.ts","../src/is-same-type.ts","../src/is-compatible-type.ts"],"sourcesContent":["import { z, type ZodType } from \"zod\";\n\nexport interface IsSameTypeOptions {\n deep: true;\n /**\n * Ignore all specific validations like min, max, length, email etc.\n *\n * You still can use `interceptor` to validate the type manually.\n */\n ignoreValidations: true;\n ignoreOptional: boolean;\n ignoreNullable: boolean;\n ignoreReadOnly: false;\n ignoreBranded: boolean;\n ignoreIntersectionsOrder: false;\n /**\n * A function that provides custom logic for comparing two ZodType instances.\n *\n * If the function returns `true` or `false`, the result will be used as the comparison result.\n * Otherwise, the default comparison logic will be used.\n *\n */\n interceptor: (\n a: ZodType,\n b: ZodType,\n options: IsSameTypeOptions,\n ) => boolean | void;\n}\n\nexport interface IsCompatibleTypeOptions extends IsSameTypeOptions {\n ignoreOptional: false;\n ignoreNullable: false;\n}\n\nexport const DEFAULT_COMPARE_TYPE_OPTIONS = {\n deep: true,\n ignoreOptional: false,\n ignoreNullable: false,\n ignoreReadOnly: false,\n ignoreBranded: false,\n ignoreValidations: true,\n ignoreIntersectionsOrder: false,\n interceptor: () => {},\n} as const satisfies IsSameTypeOptions;\n\n// See ZodFirstPartyTypeKind\nexport const isPrimitiveType = (a: ZodType): boolean => {\n return (\n a instanceof z.ZodString ||\n a instanceof z.ZodNumber ||\n a instanceof z.ZodNaN ||\n a instanceof z.ZodBigInt ||\n a instanceof z.ZodBoolean ||\n a instanceof z.ZodDate ||\n a instanceof z.ZodSymbol ||\n a instanceof z.ZodUndefined ||\n a instanceof z.ZodNull ||\n a instanceof z.ZodAny ||\n a instanceof z.ZodUnknown ||\n a instanceof z.ZodNever ||\n a instanceof z.ZodVoid\n );\n};\n","import type { EnumLike, ZodType } from \"zod\";\nimport { z } from \"zod\";\nimport {\n type IsSameTypeOptions,\n DEFAULT_COMPARE_TYPE_OPTIONS,\n isPrimitiveType,\n} from \"./utils.ts\";\n\n/**\n * isSameType is a function that checks if two ZodTypes are the same.\n *\n * Caveats:\n * - The function does not validate specific criteria such as min or max values, length, email, etc.\n * - It excludes comparisons involving methods like .describe(), .catch(), .default(), .refine(), and .transform().\n * - When comparing definitions with .or and .and, they are assessed sequentially based on their order.\n *\n * @param a - The first ZodType to compare.\n * @param b - The second ZodType to compare.\n * @returns A boolean indicating whether the two types are the same.\n *\n * @throws Will throw an error if it encounters an unknown type.\n *\n * @example\n * ```ts\n * isSameType(z.string(), z.string()); // true\n * isSameType(z.string(), z.number()); // false\n * ```\n */\nexport const isSameType = (\n a: ZodType,\n b: ZodType,\n options?: Partial<IsSameTypeOptions>,\n): boolean => {\n const opts = { ...DEFAULT_COMPARE_TYPE_OPTIONS, ...options };\n const interceptorResult = opts.interceptor(a, b, opts);\n if (interceptorResult === true || interceptorResult === false) {\n return interceptorResult;\n }\n\n if (a === undefined || b === undefined) {\n throw new Error(\"Failed to compare type! \" + a + \" \" + b);\n }\n\n if (a === b) {\n return true;\n }\n\n // compare constructor\n if (a.constructor !== b.constructor) {\n // https://stackoverflow.com/questions/24959862/how-to-tell-if-two-javascript-instances-are-of-the-same-class-type\n return false;\n }\n // See https://github.com/colinhacks/zod/blob/master/src/types.ts\n if (!(\"typeName\" in a._def) || !(\"typeName\" in b._def)) {\n throw new Error(\"Failed to compare type! \" + a._def + \" \" + b._def);\n }\n if (a._def.typeName !== b._def.typeName) {\n return false;\n }\n\n // ZodBranded\n if (opts.ignoreBranded) {\n if (a instanceof z.ZodBranded) {\n a = a.unwrap();\n }\n if (b instanceof z.ZodBranded) {\n b = b.unwrap();\n }\n return isSameType(a, b, opts);\n } else {\n if (a instanceof z.ZodBranded || b instanceof z.ZodBranded) {\n // We can not distinguish different branded type\n // throw new Error(\"Can not distinguish different branded type!\");\n return false;\n }\n }\n\n // ZodPromise ZodOptional ZodNullable ZodBranded\n if (\"unwrap\" in a && typeof a.unwrap === \"function\") {\n if (!(\"unwrap\" in b && typeof b.unwrap === \"function\")) {\n return false;\n }\n return isSameType(a.unwrap(), b.unwrap(), opts);\n }\n\n if (!opts.ignoreOptional && a.isOptional() !== b.isOptional()) return false;\n if (!opts.ignoreNullable && a.isNullable() !== b.isNullable()) return false;\n\n if (isPrimitiveType(a)) {\n // Already assert a and b are the same constructor\n return true;\n }\n\n // ZodObject\n if (a instanceof z.ZodObject && b instanceof z.ZodObject) {\n const aShape = a.shape;\n const bShape = b.shape;\n if (Object.keys(aShape).length !== Object.keys(bShape).length) return false;\n for (const key in aShape) {\n if (!(key in bShape)) return false;\n if (!isSameType(aShape[key], bShape[key], opts)) return false;\n }\n return true;\n }\n\n // ZodArray\n if (a instanceof z.ZodArray && b instanceof z.ZodArray) {\n return isSameType(a.element, b.element, opts);\n }\n\n // ZodTuple\n if (a instanceof z.ZodTuple && b instanceof z.ZodTuple) {\n if (a.items.length !== b.items.length) return false;\n for (let i = 0; i < a.items.length; i++) {\n if (!isSameType(a.items[i], b.items[i], opts)) return false;\n }\n // Compare rest\n if (a._def.rest || b._def.rest) {\n // If one has rest, the other must have rest\n if (!a._def.rest || !b._def.rest) return false;\n return isSameType(a._def.rest, b._def.rest, opts);\n }\n return true;\n }\n\n // ZodLiteral\n if (a instanceof z.ZodLiteral && b instanceof z.ZodLiteral) {\n return a.value === b.value;\n }\n\n // ZodIntersection aka and\n if (a instanceof z.ZodIntersection && b instanceof z.ZodIntersection) {\n return (\n isSameType(a._def.left, b._def.left, opts) &&\n isSameType(a._def.right, b._def.right, opts)\n );\n }\n\n // ZodUnion aka or\n if (a instanceof z.ZodUnion && b instanceof z.ZodUnion) {\n if (a.options.length !== b.options.length) return false;\n for (let i = 0; i < a.options.length; i++) {\n if (!isSameType(a.options[i], b.options[i], opts)) return false;\n }\n return true;\n }\n\n // ZodReadonly\n if (a instanceof z.ZodReadonly && b instanceof z.ZodReadonly) {\n return isSameType(a._def.innerType, b._def.innerType, opts);\n }\n\n // ZodRecord / ZodMap\n if (\n (a instanceof z.ZodRecord && b instanceof z.ZodRecord) ||\n (a instanceof z.ZodMap && b instanceof z.ZodMap)\n ) {\n return (\n isSameType(a.keySchema, b.keySchema, opts) &&\n isSameType(a.valueSchema, b.valueSchema, opts)\n );\n }\n\n // ZodSet\n if (a instanceof z.ZodSet && b instanceof z.ZodSet) {\n return isSameType(a._def.valueType, b._def.valueType, opts);\n }\n\n // ZodFunction\n if (a instanceof z.ZodFunction && b instanceof z.ZodFunction) {\n return (\n isSameType(a.parameters(), b.parameters(), opts) &&\n isSameType(a.returnType(), b.returnType(), opts)\n );\n }\n\n // ZodEnum\n if (a instanceof z.ZodEnum && b instanceof z.ZodEnum) {\n const optionsA: [string, ...string[]] = a.options;\n const optionsB: [string, ...string[]] = b.options;\n if (optionsA.length !== optionsB.length) return false;\n for (let i = 0; i < optionsA.length; i++) {\n if (optionsA[i] !== optionsB[i]) return false;\n }\n return true;\n }\n\n // ZodNativeEnum\n if (a instanceof z.ZodNativeEnum && b instanceof z.ZodNativeEnum) {\n const enumA: EnumLike = a.enum;\n const enumB: EnumLike = b.enum;\n if (Object.keys(enumA).length !== Object.keys(enumB).length) return false;\n for (const key in enumA) {\n if (enumA[key] !== enumB[key]) return false;\n }\n return true;\n }\n\n // ZodLazy\n // ZodEffects\n // ZodDefault\n // ZodCatch\n // ZodPipeline\n // ZodTransformer\n // ZodError\n console.error('Failed to compare type! \"' + a, b);\n throw new Error(\"Unknown type! \" + a._def.typeName + \" \" + b._def.typeName);\n};\n","import { z, type ZodType } from \"zod\";\nimport { isSameType } from \"./is-same-type.ts\";\nimport {\n DEFAULT_COMPARE_TYPE_OPTIONS,\n type IsCompatibleTypeOptions,\n} from \"./utils.ts\";\n\n/**\n * Check if a the higherType matches the lowerType\n *\n * @deprecated This a unstable API and still in development\n *\n * @param higherType The looser type\n * @param lowerType The stricter type\n *\n * @example\n * ```ts\n * isCompatibleType(z.string(), z.string()); // true\n *\n * isCompatibleType(\n * z.object({ name: z.string(), other: z.number() }),\n * z.object({ name: z.string() })\n * );\n * // true\n * ```\n */\nexport const isCompatibleType = (\n higherType: ZodType,\n lowerType: ZodType,\n options?: Partial<IsCompatibleTypeOptions>,\n): boolean => {\n const opts: IsCompatibleTypeOptions = {\n ...DEFAULT_COMPARE_TYPE_OPTIONS,\n ...options,\n };\n const interceptorResult = opts.interceptor(higherType, lowerType, opts);\n if (interceptorResult === true || interceptorResult === false) {\n return interceptorResult;\n }\n if (isSameType(higherType, lowerType, opts)) {\n return true;\n }\n\n if (!(\"typeName\" in higherType._def) || !(\"typeName\" in lowerType._def)) {\n throw new Error(\n \"Failed to compare type! \" + higherType._def + \" \" + lowerType._def,\n );\n }\n\n if (\n lowerType instanceof z.ZodOptional ||\n lowerType instanceof z.ZodNullable\n ) {\n return isCompatibleType(higherType, lowerType.unwrap(), opts);\n }\n\n // ZodUnion aka or\n if (higherType instanceof z.ZodUnion && lowerType instanceof z.ZodUnion) {\n for (let i = 0; i < higherType.options.length; i++) {\n const match = lowerType.options.some((option: ZodType) =>\n isCompatibleType(option, lowerType.options[i], opts),\n );\n if (!match) return false;\n }\n return true;\n }\n if (higherType instanceof z.ZodUnion) {\n return higherType.options.every((option: ZodType) =>\n isCompatibleType(option, lowerType, opts),\n );\n }\n if (lowerType instanceof z.ZodUnion) {\n return lowerType.options.some((option: ZodType) =>\n isCompatibleType(higherType, option, opts),\n );\n }\n\n // compare constructor\n if (higherType.constructor !== lowerType.constructor) {\n return false;\n }\n\n // ZodObject\n if (higherType instanceof z.ZodObject && lowerType instanceof z.ZodObject) {\n const superTypeShape = higherType.shape;\n const subTypeShape = lowerType.shape;\n if (Object.keys(superTypeShape).length < Object.keys(subTypeShape).length)\n return false;\n for (const key in subTypeShape) {\n if (!(key in superTypeShape)) return false;\n if (!isCompatibleType(superTypeShape[key], subTypeShape[key], opts)) {\n return false;\n }\n }\n return true;\n }\n\n // ZodArray\n if (higherType instanceof z.ZodArray && lowerType instanceof z.ZodArray) {\n return isCompatibleType(higherType.element, lowerType.element, opts);\n }\n\n // ZodTuple\n if (higherType instanceof z.ZodTuple && lowerType instanceof z.ZodTuple) {\n if (higherType.items.length < lowerType.items.length) return false;\n for (let i = 0; i < lowerType.items.length; i++) {\n if (!isCompatibleType(higherType.items[i], lowerType.items[i], opts)) {\n return false;\n }\n }\n // Check rest\n if (lowerType._def.rest) {\n if (!higherType._def.rest) return false;\n return isCompatibleType(higherType._def.rest, lowerType._def.rest, opts);\n }\n return true;\n }\n\n throw new Error(\n \"Failed to compare types!\" +\n higherType._def.typeName +\n \" \" +\n lowerType._def.typeName,\n );\n};\n"],"names":["DEFAULT_COMPARE_TYPE_OPTIONS","isPrimitiveType","a","z","isSameType","b","options","opts","interceptorResult","aShape","bShape","key","i","optionsA","optionsB","enumA","enumB","isCompatibleType","higherType","lowerType","option","superTypeShape","subTypeShape"],"mappings":"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"}
@@ -0,0 +1,74 @@
1
+ import { ZodType } from 'zod';
2
+
3
+ /**
4
+ * Check if a the higherType matches the lowerType
5
+ *
6
+ * @deprecated This a unstable API and still in development
7
+ *
8
+ * @param higherType The looser type
9
+ * @param lowerType The stricter type
10
+ *
11
+ * @example
12
+ * ```ts
13
+ * isCompatibleType(z.string(), z.string()); // true
14
+ *
15
+ * isCompatibleType(
16
+ * z.object({ name: z.string(), other: z.number() }),
17
+ * z.object({ name: z.string() })
18
+ * );
19
+ * // true
20
+ * ```
21
+ */
22
+ export declare const isCompatibleType: (higherType: ZodType, lowerType: ZodType, options?: Partial<IsCompatibleTypeOptions>) => boolean;
23
+
24
+ declare interface IsCompatibleTypeOptions extends IsSameTypeOptions {
25
+ ignoreOptional: false;
26
+ ignoreNullable: false;
27
+ }
28
+
29
+ /**
30
+ * isSameType is a function that checks if two ZodTypes are the same.
31
+ *
32
+ * Caveats:
33
+ * - The function does not validate specific criteria such as min or max values, length, email, etc.
34
+ * - It excludes comparisons involving methods like .describe(), .catch(), .default(), .refine(), and .transform().
35
+ * - When comparing definitions with .or and .and, they are assessed sequentially based on their order.
36
+ *
37
+ * @param a - The first ZodType to compare.
38
+ * @param b - The second ZodType to compare.
39
+ * @returns A boolean indicating whether the two types are the same.
40
+ *
41
+ * @throws Will throw an error if it encounters an unknown type.
42
+ *
43
+ * @example
44
+ * ```ts
45
+ * isSameType(z.string(), z.string()); // true
46
+ * isSameType(z.string(), z.number()); // false
47
+ * ```
48
+ */
49
+ export declare const isSameType: (a: ZodType, b: ZodType, options?: Partial<IsSameTypeOptions>) => boolean;
50
+
51
+ export declare interface IsSameTypeOptions {
52
+ deep: true;
53
+ /**
54
+ * Ignore all specific validations like min, max, length, email etc.
55
+ *
56
+ * You still can use `interceptor` to validate the type manually.
57
+ */
58
+ ignoreValidations: true;
59
+ ignoreOptional: boolean;
60
+ ignoreNullable: boolean;
61
+ ignoreReadOnly: false;
62
+ ignoreBranded: boolean;
63
+ ignoreIntersectionsOrder: false;
64
+ /**
65
+ * A function that provides custom logic for comparing two ZodType instances.
66
+ *
67
+ * If the function returns `true` or `false`, the result will be used as the comparison result.
68
+ * Otherwise, the default comparison logic will be used.
69
+ *
70
+ */
71
+ interceptor: (a: ZodType, b: ZodType, options: IsSameTypeOptions) => boolean | void;
72
+ }
73
+
74
+ export { }
package/dist/index.js ADDED
@@ -0,0 +1,154 @@
1
+ import { z as t } from "zod";
2
+ const a = {
3
+ deep: !0,
4
+ ignoreOptional: !1,
5
+ ignoreNullable: !1,
6
+ ignoreReadOnly: !1,
7
+ ignoreBranded: !1,
8
+ ignoreValidations: !0,
9
+ ignoreIntersectionsOrder: !1,
10
+ interceptor: () => {
11
+ }
12
+ }, l = (e) => e instanceof t.ZodString || e instanceof t.ZodNumber || e instanceof t.ZodNaN || e instanceof t.ZodBigInt || e instanceof t.ZodBoolean || e instanceof t.ZodDate || e instanceof t.ZodSymbol || e instanceof t.ZodUndefined || e instanceof t.ZodNull || e instanceof t.ZodAny || e instanceof t.ZodUnknown || e instanceof t.ZodNever || e instanceof t.ZodVoid, f = (e, n, d) => {
13
+ const r = { ...a, ...d }, u = r.interceptor(e, n, r);
14
+ if (u === !0 || u === !1)
15
+ return u;
16
+ if (e === void 0 || n === void 0)
17
+ throw new Error("Failed to compare type! " + e + " " + n);
18
+ if (e === n)
19
+ return !0;
20
+ if (e.constructor !== n.constructor)
21
+ return !1;
22
+ if (!("typeName" in e._def) || !("typeName" in n._def))
23
+ throw new Error("Failed to compare type! " + e._def + " " + n._def);
24
+ if (e._def.typeName !== n._def.typeName)
25
+ return !1;
26
+ if (r.ignoreBranded)
27
+ return e instanceof t.ZodBranded && (e = e.unwrap()), n instanceof t.ZodBranded && (n = n.unwrap()), f(e, n, r);
28
+ if (e instanceof t.ZodBranded || n instanceof t.ZodBranded)
29
+ return !1;
30
+ if ("unwrap" in e && typeof e.unwrap == "function")
31
+ return "unwrap" in n && typeof n.unwrap == "function" ? f(e.unwrap(), n.unwrap(), r) : !1;
32
+ if (!r.ignoreOptional && e.isOptional() !== n.isOptional() || !r.ignoreNullable && e.isNullable() !== n.isNullable())
33
+ return !1;
34
+ if (l(e))
35
+ return !0;
36
+ if (e instanceof t.ZodObject && n instanceof t.ZodObject) {
37
+ const o = e.shape, s = n.shape;
38
+ if (Object.keys(o).length !== Object.keys(s).length)
39
+ return !1;
40
+ for (const i in o)
41
+ if (!(i in s) || !f(o[i], s[i], r))
42
+ return !1;
43
+ return !0;
44
+ }
45
+ if (e instanceof t.ZodArray && n instanceof t.ZodArray)
46
+ return f(e.element, n.element, r);
47
+ if (e instanceof t.ZodTuple && n instanceof t.ZodTuple) {
48
+ if (e.items.length !== n.items.length)
49
+ return !1;
50
+ for (let o = 0; o < e.items.length; o++)
51
+ if (!f(e.items[o], n.items[o], r))
52
+ return !1;
53
+ return e._def.rest || n._def.rest ? !e._def.rest || !n._def.rest ? !1 : f(e._def.rest, n._def.rest, r) : !0;
54
+ }
55
+ if (e instanceof t.ZodLiteral && n instanceof t.ZodLiteral)
56
+ return e.value === n.value;
57
+ if (e instanceof t.ZodIntersection && n instanceof t.ZodIntersection)
58
+ return f(e._def.left, n._def.left, r) && f(e._def.right, n._def.right, r);
59
+ if (e instanceof t.ZodUnion && n instanceof t.ZodUnion) {
60
+ if (e.options.length !== n.options.length)
61
+ return !1;
62
+ for (let o = 0; o < e.options.length; o++)
63
+ if (!f(e.options[o], n.options[o], r))
64
+ return !1;
65
+ return !0;
66
+ }
67
+ if (e instanceof t.ZodReadonly && n instanceof t.ZodReadonly)
68
+ return f(e._def.innerType, n._def.innerType, r);
69
+ if (e instanceof t.ZodRecord && n instanceof t.ZodRecord || e instanceof t.ZodMap && n instanceof t.ZodMap)
70
+ return f(e.keySchema, n.keySchema, r) && f(e.valueSchema, n.valueSchema, r);
71
+ if (e instanceof t.ZodSet && n instanceof t.ZodSet)
72
+ return f(e._def.valueType, n._def.valueType, r);
73
+ if (e instanceof t.ZodFunction && n instanceof t.ZodFunction)
74
+ return f(e.parameters(), n.parameters(), r) && f(e.returnType(), n.returnType(), r);
75
+ if (e instanceof t.ZodEnum && n instanceof t.ZodEnum) {
76
+ const o = e.options, s = n.options;
77
+ if (o.length !== s.length)
78
+ return !1;
79
+ for (let i = 0; i < o.length; i++)
80
+ if (o[i] !== s[i])
81
+ return !1;
82
+ return !0;
83
+ }
84
+ if (e instanceof t.ZodNativeEnum && n instanceof t.ZodNativeEnum) {
85
+ const o = e.enum, s = n.enum;
86
+ if (Object.keys(o).length !== Object.keys(s).length)
87
+ return !1;
88
+ for (const i in o)
89
+ if (o[i] !== s[i])
90
+ return !1;
91
+ return !0;
92
+ }
93
+ throw console.error('Failed to compare type! "' + e, n), new Error("Unknown type! " + e._def.typeName + " " + n._def.typeName);
94
+ }, c = (e, n, d) => {
95
+ const r = {
96
+ ...a,
97
+ ...d
98
+ }, u = r.interceptor(e, n, r);
99
+ if (u === !0 || u === !1)
100
+ return u;
101
+ if (f(e, n, r))
102
+ return !0;
103
+ if (!("typeName" in e._def) || !("typeName" in n._def))
104
+ throw new Error(
105
+ "Failed to compare type! " + e._def + " " + n._def
106
+ );
107
+ if (n instanceof t.ZodOptional || n instanceof t.ZodNullable)
108
+ return c(e, n.unwrap(), r);
109
+ if (e instanceof t.ZodUnion && n instanceof t.ZodUnion) {
110
+ for (let o = 0; o < e.options.length; o++)
111
+ if (!n.options.some(
112
+ (i) => c(i, n.options[o], r)
113
+ ))
114
+ return !1;
115
+ return !0;
116
+ }
117
+ if (e instanceof t.ZodUnion)
118
+ return e.options.every(
119
+ (o) => c(o, n, r)
120
+ );
121
+ if (n instanceof t.ZodUnion)
122
+ return n.options.some(
123
+ (o) => c(e, o, r)
124
+ );
125
+ if (e.constructor !== n.constructor)
126
+ return !1;
127
+ if (e instanceof t.ZodObject && n instanceof t.ZodObject) {
128
+ const o = e.shape, s = n.shape;
129
+ if (Object.keys(o).length < Object.keys(s).length)
130
+ return !1;
131
+ for (const i in s)
132
+ if (!(i in o) || !c(o[i], s[i], r))
133
+ return !1;
134
+ return !0;
135
+ }
136
+ if (e instanceof t.ZodArray && n instanceof t.ZodArray)
137
+ return c(e.element, n.element, r);
138
+ if (e instanceof t.ZodTuple && n instanceof t.ZodTuple) {
139
+ if (e.items.length < n.items.length)
140
+ return !1;
141
+ for (let o = 0; o < n.items.length; o++)
142
+ if (!c(e.items[o], n.items[o], r))
143
+ return !1;
144
+ return n._def.rest ? e._def.rest ? c(e._def.rest, n._def.rest, r) : !1 : !0;
145
+ }
146
+ throw new Error(
147
+ "Failed to compare types!" + e._def.typeName + " " + n._def.typeName
148
+ );
149
+ };
150
+ export {
151
+ c as isCompatibleType,
152
+ f as isSameType
153
+ };
154
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":["../src/utils.ts","../src/is-same-type.ts","../src/is-compatible-type.ts"],"sourcesContent":["import { z, type ZodType } from \"zod\";\n\nexport interface IsSameTypeOptions {\n deep: true;\n /**\n * Ignore all specific validations like min, max, length, email etc.\n *\n * You still can use `interceptor` to validate the type manually.\n */\n ignoreValidations: true;\n ignoreOptional: boolean;\n ignoreNullable: boolean;\n ignoreReadOnly: false;\n ignoreBranded: boolean;\n ignoreIntersectionsOrder: false;\n /**\n * A function that provides custom logic for comparing two ZodType instances.\n *\n * If the function returns `true` or `false`, the result will be used as the comparison result.\n * Otherwise, the default comparison logic will be used.\n *\n */\n interceptor: (\n a: ZodType,\n b: ZodType,\n options: IsSameTypeOptions,\n ) => boolean | void;\n}\n\nexport interface IsCompatibleTypeOptions extends IsSameTypeOptions {\n ignoreOptional: false;\n ignoreNullable: false;\n}\n\nexport const DEFAULT_COMPARE_TYPE_OPTIONS = {\n deep: true,\n ignoreOptional: false,\n ignoreNullable: false,\n ignoreReadOnly: false,\n ignoreBranded: false,\n ignoreValidations: true,\n ignoreIntersectionsOrder: false,\n interceptor: () => {},\n} as const satisfies IsSameTypeOptions;\n\n// See ZodFirstPartyTypeKind\nexport const isPrimitiveType = (a: ZodType): boolean => {\n return (\n a instanceof z.ZodString ||\n a instanceof z.ZodNumber ||\n a instanceof z.ZodNaN ||\n a instanceof z.ZodBigInt ||\n a instanceof z.ZodBoolean ||\n a instanceof z.ZodDate ||\n a instanceof z.ZodSymbol ||\n a instanceof z.ZodUndefined ||\n a instanceof z.ZodNull ||\n a instanceof z.ZodAny ||\n a instanceof z.ZodUnknown ||\n a instanceof z.ZodNever ||\n a instanceof z.ZodVoid\n );\n};\n","import type { EnumLike, ZodType } from \"zod\";\nimport { z } from \"zod\";\nimport {\n type IsSameTypeOptions,\n DEFAULT_COMPARE_TYPE_OPTIONS,\n isPrimitiveType,\n} from \"./utils.ts\";\n\n/**\n * isSameType is a function that checks if two ZodTypes are the same.\n *\n * Caveats:\n * - The function does not validate specific criteria such as min or max values, length, email, etc.\n * - It excludes comparisons involving methods like .describe(), .catch(), .default(), .refine(), and .transform().\n * - When comparing definitions with .or and .and, they are assessed sequentially based on their order.\n *\n * @param a - The first ZodType to compare.\n * @param b - The second ZodType to compare.\n * @returns A boolean indicating whether the two types are the same.\n *\n * @throws Will throw an error if it encounters an unknown type.\n *\n * @example\n * ```ts\n * isSameType(z.string(), z.string()); // true\n * isSameType(z.string(), z.number()); // false\n * ```\n */\nexport const isSameType = (\n a: ZodType,\n b: ZodType,\n options?: Partial<IsSameTypeOptions>,\n): boolean => {\n const opts = { ...DEFAULT_COMPARE_TYPE_OPTIONS, ...options };\n const interceptorResult = opts.interceptor(a, b, opts);\n if (interceptorResult === true || interceptorResult === false) {\n return interceptorResult;\n }\n\n if (a === undefined || b === undefined) {\n throw new Error(\"Failed to compare type! \" + a + \" \" + b);\n }\n\n if (a === b) {\n return true;\n }\n\n // compare constructor\n if (a.constructor !== b.constructor) {\n // https://stackoverflow.com/questions/24959862/how-to-tell-if-two-javascript-instances-are-of-the-same-class-type\n return false;\n }\n // See https://github.com/colinhacks/zod/blob/master/src/types.ts\n if (!(\"typeName\" in a._def) || !(\"typeName\" in b._def)) {\n throw new Error(\"Failed to compare type! \" + a._def + \" \" + b._def);\n }\n if (a._def.typeName !== b._def.typeName) {\n return false;\n }\n\n // ZodBranded\n if (opts.ignoreBranded) {\n if (a instanceof z.ZodBranded) {\n a = a.unwrap();\n }\n if (b instanceof z.ZodBranded) {\n b = b.unwrap();\n }\n return isSameType(a, b, opts);\n } else {\n if (a instanceof z.ZodBranded || b instanceof z.ZodBranded) {\n // We can not distinguish different branded type\n // throw new Error(\"Can not distinguish different branded type!\");\n return false;\n }\n }\n\n // ZodPromise ZodOptional ZodNullable ZodBranded\n if (\"unwrap\" in a && typeof a.unwrap === \"function\") {\n if (!(\"unwrap\" in b && typeof b.unwrap === \"function\")) {\n return false;\n }\n return isSameType(a.unwrap(), b.unwrap(), opts);\n }\n\n if (!opts.ignoreOptional && a.isOptional() !== b.isOptional()) return false;\n if (!opts.ignoreNullable && a.isNullable() !== b.isNullable()) return false;\n\n if (isPrimitiveType(a)) {\n // Already assert a and b are the same constructor\n return true;\n }\n\n // ZodObject\n if (a instanceof z.ZodObject && b instanceof z.ZodObject) {\n const aShape = a.shape;\n const bShape = b.shape;\n if (Object.keys(aShape).length !== Object.keys(bShape).length) return false;\n for (const key in aShape) {\n if (!(key in bShape)) return false;\n if (!isSameType(aShape[key], bShape[key], opts)) return false;\n }\n return true;\n }\n\n // ZodArray\n if (a instanceof z.ZodArray && b instanceof z.ZodArray) {\n return isSameType(a.element, b.element, opts);\n }\n\n // ZodTuple\n if (a instanceof z.ZodTuple && b instanceof z.ZodTuple) {\n if (a.items.length !== b.items.length) return false;\n for (let i = 0; i < a.items.length; i++) {\n if (!isSameType(a.items[i], b.items[i], opts)) return false;\n }\n // Compare rest\n if (a._def.rest || b._def.rest) {\n // If one has rest, the other must have rest\n if (!a._def.rest || !b._def.rest) return false;\n return isSameType(a._def.rest, b._def.rest, opts);\n }\n return true;\n }\n\n // ZodLiteral\n if (a instanceof z.ZodLiteral && b instanceof z.ZodLiteral) {\n return a.value === b.value;\n }\n\n // ZodIntersection aka and\n if (a instanceof z.ZodIntersection && b instanceof z.ZodIntersection) {\n return (\n isSameType(a._def.left, b._def.left, opts) &&\n isSameType(a._def.right, b._def.right, opts)\n );\n }\n\n // ZodUnion aka or\n if (a instanceof z.ZodUnion && b instanceof z.ZodUnion) {\n if (a.options.length !== b.options.length) return false;\n for (let i = 0; i < a.options.length; i++) {\n if (!isSameType(a.options[i], b.options[i], opts)) return false;\n }\n return true;\n }\n\n // ZodReadonly\n if (a instanceof z.ZodReadonly && b instanceof z.ZodReadonly) {\n return isSameType(a._def.innerType, b._def.innerType, opts);\n }\n\n // ZodRecord / ZodMap\n if (\n (a instanceof z.ZodRecord && b instanceof z.ZodRecord) ||\n (a instanceof z.ZodMap && b instanceof z.ZodMap)\n ) {\n return (\n isSameType(a.keySchema, b.keySchema, opts) &&\n isSameType(a.valueSchema, b.valueSchema, opts)\n );\n }\n\n // ZodSet\n if (a instanceof z.ZodSet && b instanceof z.ZodSet) {\n return isSameType(a._def.valueType, b._def.valueType, opts);\n }\n\n // ZodFunction\n if (a instanceof z.ZodFunction && b instanceof z.ZodFunction) {\n return (\n isSameType(a.parameters(), b.parameters(), opts) &&\n isSameType(a.returnType(), b.returnType(), opts)\n );\n }\n\n // ZodEnum\n if (a instanceof z.ZodEnum && b instanceof z.ZodEnum) {\n const optionsA: [string, ...string[]] = a.options;\n const optionsB: [string, ...string[]] = b.options;\n if (optionsA.length !== optionsB.length) return false;\n for (let i = 0; i < optionsA.length; i++) {\n if (optionsA[i] !== optionsB[i]) return false;\n }\n return true;\n }\n\n // ZodNativeEnum\n if (a instanceof z.ZodNativeEnum && b instanceof z.ZodNativeEnum) {\n const enumA: EnumLike = a.enum;\n const enumB: EnumLike = b.enum;\n if (Object.keys(enumA).length !== Object.keys(enumB).length) return false;\n for (const key in enumA) {\n if (enumA[key] !== enumB[key]) return false;\n }\n return true;\n }\n\n // ZodLazy\n // ZodEffects\n // ZodDefault\n // ZodCatch\n // ZodPipeline\n // ZodTransformer\n // ZodError\n console.error('Failed to compare type! \"' + a, b);\n throw new Error(\"Unknown type! \" + a._def.typeName + \" \" + b._def.typeName);\n};\n","import { z, type ZodType } from \"zod\";\nimport { isSameType } from \"./is-same-type.ts\";\nimport {\n DEFAULT_COMPARE_TYPE_OPTIONS,\n type IsCompatibleTypeOptions,\n} from \"./utils.ts\";\n\n/**\n * Check if a the higherType matches the lowerType\n *\n * @deprecated This a unstable API and still in development\n *\n * @param higherType The looser type\n * @param lowerType The stricter type\n *\n * @example\n * ```ts\n * isCompatibleType(z.string(), z.string()); // true\n *\n * isCompatibleType(\n * z.object({ name: z.string(), other: z.number() }),\n * z.object({ name: z.string() })\n * );\n * // true\n * ```\n */\nexport const isCompatibleType = (\n higherType: ZodType,\n lowerType: ZodType,\n options?: Partial<IsCompatibleTypeOptions>,\n): boolean => {\n const opts: IsCompatibleTypeOptions = {\n ...DEFAULT_COMPARE_TYPE_OPTIONS,\n ...options,\n };\n const interceptorResult = opts.interceptor(higherType, lowerType, opts);\n if (interceptorResult === true || interceptorResult === false) {\n return interceptorResult;\n }\n if (isSameType(higherType, lowerType, opts)) {\n return true;\n }\n\n if (!(\"typeName\" in higherType._def) || !(\"typeName\" in lowerType._def)) {\n throw new Error(\n \"Failed to compare type! \" + higherType._def + \" \" + lowerType._def,\n );\n }\n\n if (\n lowerType instanceof z.ZodOptional ||\n lowerType instanceof z.ZodNullable\n ) {\n return isCompatibleType(higherType, lowerType.unwrap(), opts);\n }\n\n // ZodUnion aka or\n if (higherType instanceof z.ZodUnion && lowerType instanceof z.ZodUnion) {\n for (let i = 0; i < higherType.options.length; i++) {\n const match = lowerType.options.some((option: ZodType) =>\n isCompatibleType(option, lowerType.options[i], opts),\n );\n if (!match) return false;\n }\n return true;\n }\n if (higherType instanceof z.ZodUnion) {\n return higherType.options.every((option: ZodType) =>\n isCompatibleType(option, lowerType, opts),\n );\n }\n if (lowerType instanceof z.ZodUnion) {\n return lowerType.options.some((option: ZodType) =>\n isCompatibleType(higherType, option, opts),\n );\n }\n\n // compare constructor\n if (higherType.constructor !== lowerType.constructor) {\n return false;\n }\n\n // ZodObject\n if (higherType instanceof z.ZodObject && lowerType instanceof z.ZodObject) {\n const superTypeShape = higherType.shape;\n const subTypeShape = lowerType.shape;\n if (Object.keys(superTypeShape).length < Object.keys(subTypeShape).length)\n return false;\n for (const key in subTypeShape) {\n if (!(key in superTypeShape)) return false;\n if (!isCompatibleType(superTypeShape[key], subTypeShape[key], opts)) {\n return false;\n }\n }\n return true;\n }\n\n // ZodArray\n if (higherType instanceof z.ZodArray && lowerType instanceof z.ZodArray) {\n return isCompatibleType(higherType.element, lowerType.element, opts);\n }\n\n // ZodTuple\n if (higherType instanceof z.ZodTuple && lowerType instanceof z.ZodTuple) {\n if (higherType.items.length < lowerType.items.length) return false;\n for (let i = 0; i < lowerType.items.length; i++) {\n if (!isCompatibleType(higherType.items[i], lowerType.items[i], opts)) {\n return false;\n }\n }\n // Check rest\n if (lowerType._def.rest) {\n if (!higherType._def.rest) return false;\n return isCompatibleType(higherType._def.rest, lowerType._def.rest, opts);\n }\n return true;\n }\n\n throw new Error(\n \"Failed to compare types!\" +\n higherType._def.typeName +\n \" \" +\n lowerType._def.typeName,\n );\n};\n"],"names":["DEFAULT_COMPARE_TYPE_OPTIONS","isPrimitiveType","a","z","isSameType","b","options","opts","interceptorResult","aShape","bShape","key","i","optionsA","optionsB","enumA","enumB","isCompatibleType","higherType","lowerType","option","superTypeShape","subTypeShape"],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,64 @@
1
+ {
2
+ "name": "zod-compare",
3
+ "version": "0.1.1",
4
+ "description": "Compare two Zod schemas recursively.",
5
+ "keywords": [
6
+ "zod",
7
+ "compare",
8
+ "comparator",
9
+ "schema",
10
+ "type",
11
+ "typescript",
12
+ "validation"
13
+ ],
14
+ "repository": {
15
+ "type": "git",
16
+ "url": "https://github.com/lawvs/zod-compare.git"
17
+ },
18
+ "license": "MIT",
19
+ "author": "whitewater <me@waterwater.moe>",
20
+ "sideEffects": false,
21
+ "type": "module",
22
+ "main": "dist/index.js",
23
+ "files": [
24
+ "src",
25
+ "dist"
26
+ ],
27
+ "devDependencies": {
28
+ "@changesets/cli": "^2.27.1",
29
+ "@vitest/coverage-v8": "^1.3.1",
30
+ "prettier": "^3.2.5",
31
+ "typescript": "^5.3.3",
32
+ "vite": "^5.1.4",
33
+ "vite-plugin-dts": "^3.7.3",
34
+ "vitest": "^1.3.1",
35
+ "zod": "^3.22.4"
36
+ },
37
+ "peerDependencies": {
38
+ "zod": "^3.22.4"
39
+ },
40
+ "packageManager": "pnpm@8.15.3",
41
+ "engines": {
42
+ "node": ">=20"
43
+ },
44
+ "prettier": {},
45
+ "publishConfig": {
46
+ "access": "public"
47
+ },
48
+ "scripts": {
49
+ "build": "tsc && vite build",
50
+ "format": "prettier --check .",
51
+ "format:fix": "prettier --write .",
52
+ "typeCheck": "tsc --noEmit",
53
+ "test": "vitest",
54
+ "changeset": "changeset",
55
+ "release": "pnpm run build && changeset publish"
56
+ },
57
+ "module": "./dist/index.js",
58
+ "types": "./dist/index.d.ts",
59
+ "exports": {
60
+ "types": "./dist/index.d.ts",
61
+ "import": "./dist/index.js",
62
+ "require": "./dist/index.cjs"
63
+ }
64
+ }
@@ -0,0 +1,136 @@
1
+ import { describe, expect, test } from "vitest";
2
+ import { z } from "zod";
3
+ import { isCompatibleType } from "../is-compatible-type.ts";
4
+
5
+ describe("isCompatibleType", () => {
6
+ test("should ref same type", () => {
7
+ const uniqueType = z.string().brand("unique");
8
+ expect(isCompatibleType(uniqueType, uniqueType)).toBe(true);
9
+ });
10
+
11
+ test("compare basic type", () => {
12
+ expect(isCompatibleType(z.undefined(), z.undefined())).toBe(true);
13
+ expect(isCompatibleType(z.string(), z.string())).toBe(true);
14
+ expect(isCompatibleType(z.string(), z.number())).toBe(false);
15
+ expect(isCompatibleType(z.string().optional(), z.string())).toBe(false);
16
+ expect(isCompatibleType(z.string().optional(), z.string().optional())).toBe(
17
+ true,
18
+ );
19
+ expect(isCompatibleType(z.string().nullable(), z.string().optional())).toBe(
20
+ false,
21
+ );
22
+ expect(isCompatibleType(z.string(), z.string().nullable())).toBe(true);
23
+ expect(isCompatibleType(z.string(), z.string().optional())).toBe(true);
24
+ });
25
+
26
+ test("should compare simple object", () => {
27
+ expect(
28
+ isCompatibleType(
29
+ z.object({
30
+ name: z.string(),
31
+ other: z.number(),
32
+ }),
33
+ z.object({
34
+ name: z.string(),
35
+ }),
36
+ ),
37
+ ).toBe(true);
38
+ expect(
39
+ isCompatibleType(
40
+ z.object({
41
+ name: z.number(),
42
+ }),
43
+ z.object({
44
+ name: z.number().nullable(),
45
+ }),
46
+ ),
47
+ ).toBe(true);
48
+ expect(
49
+ isCompatibleType(
50
+ z
51
+ .object({
52
+ name: z.string().optional(),
53
+ })
54
+ .partial(),
55
+ z.object({
56
+ name: z.string(),
57
+ }),
58
+ ),
59
+ ).toBe(false);
60
+ expect(
61
+ isCompatibleType(
62
+ z.object({
63
+ name: z.string(),
64
+ }),
65
+ z
66
+ .object({
67
+ name: z.string(),
68
+ })
69
+ .partial(),
70
+ ),
71
+ ).toBe(true);
72
+ expect(
73
+ isCompatibleType(
74
+ z.object({
75
+ name: z.string().nullable(),
76
+ }),
77
+ z.object({
78
+ name: z.string().optional(),
79
+ }),
80
+ ),
81
+ ).toBe(false);
82
+ expect(
83
+ isCompatibleType(
84
+ z.object({}),
85
+ z.object({
86
+ name: z.string(),
87
+ }),
88
+ ),
89
+ ).toBe(false);
90
+ });
91
+
92
+ test("should compare rest tuple", () => {
93
+ expect(
94
+ isCompatibleType(
95
+ z.tuple([z.string(), z.string()]),
96
+ z.tuple([z.string()]),
97
+ ),
98
+ ).toBe(true);
99
+ expect(
100
+ isCompatibleType(
101
+ z.tuple([z.string(), z.string()]),
102
+ z.tuple([z.string(), z.number()]),
103
+ ),
104
+ ).toBe(false);
105
+ expect(
106
+ isCompatibleType(
107
+ z.tuple([z.string(), z.string()]).rest(z.number()),
108
+ z.tuple([z.string(), z.string()]),
109
+ ),
110
+ ).toBe(true);
111
+ expect(
112
+ isCompatibleType(
113
+ z.tuple([z.string()]),
114
+ z.tuple([z.string()]).rest(z.number()),
115
+ ),
116
+ ).toBe(false);
117
+
118
+ expect(
119
+ isCompatibleType(z.tuple([]).rest(z.number()), z.array(z.number())),
120
+ ).toBe(false);
121
+ });
122
+
123
+ test("should compare `or` type", () => {
124
+ expect(isCompatibleType(z.string(), z.string().or(z.number()))).toBe(true);
125
+ expect(
126
+ isCompatibleType(z.string(), z.number().or(z.string()).or(z.boolean())),
127
+ ).toBe(true);
128
+ expect(isCompatibleType(z.string().or(z.number()), z.string())).toBe(false);
129
+ expect(
130
+ isCompatibleType(
131
+ z.string().or(z.number()),
132
+ z.number().or(z.string()).or(z.boolean()),
133
+ ),
134
+ ).toBe(true);
135
+ });
136
+ });
@@ -0,0 +1,174 @@
1
+ import { describe, expect, test } from "vitest";
2
+ import { z } from "zod";
3
+ import { isSameType } from "../is-same-type.ts";
4
+
5
+ describe("isSameType", () => {
6
+ test("should ref same type", () => {
7
+ const uniqueType = z.string().brand("unique");
8
+ expect(isSameType(uniqueType, uniqueType)).toBe(true);
9
+ });
10
+
11
+ test("compare basic type", () => {
12
+ expect(isSameType(z.undefined(), z.undefined())).toBe(true);
13
+ expect(isSameType(z.string(), z.string())).toBe(true);
14
+ expect(isSameType(z.string(), z.number())).toBe(false);
15
+ expect(isSameType(z.string().optional(), z.string())).toBe(false);
16
+ expect(isSameType(z.string().optional(), z.string().optional())).toBe(true);
17
+ expect(isSameType(z.string().nullable(), z.string().optional())).toBe(
18
+ false,
19
+ );
20
+ });
21
+
22
+ test("should return false when compare branded type", () => {
23
+ expect(isSameType(z.string().brand("test"), z.string())).toBe(false);
24
+ expect(isSameType(z.string().brand("test"), z.string().brand("test"))).toBe(
25
+ false,
26
+ );
27
+ // expect(() =>
28
+ // isSameType(z.string().brand("test"), z.string().brand("test"))
29
+ // ).toThrowError();
30
+ });
31
+
32
+ test("should compare simple object", () => {
33
+ expect(
34
+ isSameType(
35
+ z.object({
36
+ name: z.string(),
37
+ }),
38
+ z.object({
39
+ name: z.string(),
40
+ }),
41
+ ),
42
+ ).toBe(true);
43
+ expect(
44
+ isSameType(
45
+ z.object({
46
+ name: z.string(),
47
+ }),
48
+ z.object({
49
+ name: z.number(),
50
+ }),
51
+ ),
52
+ ).toBe(false);
53
+ expect(
54
+ isSameType(
55
+ z
56
+ .object({
57
+ name: z.string(),
58
+ })
59
+ .partial(),
60
+ z.object({
61
+ name: z.string(),
62
+ }),
63
+ ),
64
+ ).toBe(false);
65
+ expect(
66
+ isSameType(
67
+ z
68
+ .object({
69
+ name: z.string(),
70
+ })
71
+ .partial(),
72
+ z
73
+ .object({
74
+ name: z.string(),
75
+ })
76
+ .partial(),
77
+ ),
78
+ ).toBe(true);
79
+ expect(
80
+ isSameType(
81
+ z.object({
82
+ name: z.string().nullable(),
83
+ }),
84
+ z.object({
85
+ name: z.string().optional(),
86
+ }),
87
+ ),
88
+ ).toBe(false);
89
+ expect(
90
+ isSameType(
91
+ z.object({}),
92
+ z.object({
93
+ name: z.string(),
94
+ }),
95
+ ),
96
+ ).toBe(false);
97
+ });
98
+
99
+ test("should compare rest tuple", () => {
100
+ expect(
101
+ isSameType(
102
+ z.tuple([z.string(), z.string()]),
103
+ z.tuple([z.string(), z.string()]),
104
+ ),
105
+ ).toBe(true);
106
+ expect(
107
+ isSameType(
108
+ z.tuple([z.string(), z.string()]),
109
+ z.tuple([z.string(), z.number()]),
110
+ ),
111
+ ).toBe(false);
112
+ expect(
113
+ isSameType(
114
+ z.tuple([z.string(), z.string()]).rest(z.number()),
115
+ z.tuple([z.string(), z.string()]),
116
+ ),
117
+ ).toBe(false);
118
+ expect(
119
+ isSameType(
120
+ z.tuple([z.string(), z.string()]).rest(z.number()),
121
+ z.tuple([z.string(), z.string()]).rest(z.number()),
122
+ ),
123
+ ).toBe(true);
124
+
125
+ expect(isSameType(z.tuple([]).rest(z.number()), z.array(z.number()))).toBe(
126
+ false,
127
+ );
128
+ });
129
+
130
+ test("should compare `and` type", () => {
131
+ expect(
132
+ isSameType(z.string().and(z.number()), z.string().and(z.number())),
133
+ ).toBe(true);
134
+ expect(
135
+ isSameType(z.number().and(z.string()), z.number().and(z.string())),
136
+ ).toBe(true);
137
+
138
+ // order matters
139
+ expect(
140
+ isSameType(z.number().and(z.string()), z.string().and(z.number())),
141
+ ).toBe(false);
142
+ });
143
+
144
+ test("should compare `or` type", () => {
145
+ expect(
146
+ isSameType(z.string().or(z.number()), z.string().or(z.number())),
147
+ ).toBe(true);
148
+ expect(
149
+ isSameType(z.number().or(z.string()), z.number().or(z.string())),
150
+ ).toBe(true);
151
+
152
+ // order matters
153
+ expect(
154
+ isSameType(z.number().or(z.string()), z.string().or(z.number())),
155
+ ).toBe(false);
156
+ });
157
+
158
+ test("should compare literal type", () => {
159
+ expect(isSameType(z.literal("test"), z.literal("test"))).toBe(true);
160
+ expect(isSameType(z.literal("test"), z.literal("test2"))).toBe(false);
161
+ });
162
+
163
+ test("should compare readonly type", () => {
164
+ expect(
165
+ isSameType(
166
+ z.object({ foo: z.string().readonly() }),
167
+ z.object({
168
+ foo: z.string().readonly(),
169
+ }),
170
+ ),
171
+ ).toBe(true);
172
+ expect(isSameType(z.string().readonly(), z.string())).toBe(false);
173
+ });
174
+ });
package/src/index.ts ADDED
@@ -0,0 +1,3 @@
1
+ export { isSameType } from "./is-same-type.ts";
2
+ export { isCompatibleType } from "./is-compatible-type.ts";
3
+ export type { IsSameTypeOptions } from "./utils.ts";
@@ -0,0 +1,125 @@
1
+ import { z, type ZodType } from "zod";
2
+ import { isSameType } from "./is-same-type.ts";
3
+ import {
4
+ DEFAULT_COMPARE_TYPE_OPTIONS,
5
+ type IsCompatibleTypeOptions,
6
+ } from "./utils.ts";
7
+
8
+ /**
9
+ * Check if a the higherType matches the lowerType
10
+ *
11
+ * @deprecated This a unstable API and still in development
12
+ *
13
+ * @param higherType The looser type
14
+ * @param lowerType The stricter type
15
+ *
16
+ * @example
17
+ * ```ts
18
+ * isCompatibleType(z.string(), z.string()); // true
19
+ *
20
+ * isCompatibleType(
21
+ * z.object({ name: z.string(), other: z.number() }),
22
+ * z.object({ name: z.string() })
23
+ * );
24
+ * // true
25
+ * ```
26
+ */
27
+ export const isCompatibleType = (
28
+ higherType: ZodType,
29
+ lowerType: ZodType,
30
+ options?: Partial<IsCompatibleTypeOptions>,
31
+ ): boolean => {
32
+ const opts: IsCompatibleTypeOptions = {
33
+ ...DEFAULT_COMPARE_TYPE_OPTIONS,
34
+ ...options,
35
+ };
36
+ const interceptorResult = opts.interceptor(higherType, lowerType, opts);
37
+ if (interceptorResult === true || interceptorResult === false) {
38
+ return interceptorResult;
39
+ }
40
+ if (isSameType(higherType, lowerType, opts)) {
41
+ return true;
42
+ }
43
+
44
+ if (!("typeName" in higherType._def) || !("typeName" in lowerType._def)) {
45
+ throw new Error(
46
+ "Failed to compare type! " + higherType._def + " " + lowerType._def,
47
+ );
48
+ }
49
+
50
+ if (
51
+ lowerType instanceof z.ZodOptional ||
52
+ lowerType instanceof z.ZodNullable
53
+ ) {
54
+ return isCompatibleType(higherType, lowerType.unwrap(), opts);
55
+ }
56
+
57
+ // ZodUnion aka or
58
+ if (higherType instanceof z.ZodUnion && lowerType instanceof z.ZodUnion) {
59
+ for (let i = 0; i < higherType.options.length; i++) {
60
+ const match = lowerType.options.some((option: ZodType) =>
61
+ isCompatibleType(option, lowerType.options[i], opts),
62
+ );
63
+ if (!match) return false;
64
+ }
65
+ return true;
66
+ }
67
+ if (higherType instanceof z.ZodUnion) {
68
+ return higherType.options.every((option: ZodType) =>
69
+ isCompatibleType(option, lowerType, opts),
70
+ );
71
+ }
72
+ if (lowerType instanceof z.ZodUnion) {
73
+ return lowerType.options.some((option: ZodType) =>
74
+ isCompatibleType(higherType, option, opts),
75
+ );
76
+ }
77
+
78
+ // compare constructor
79
+ if (higherType.constructor !== lowerType.constructor) {
80
+ return false;
81
+ }
82
+
83
+ // ZodObject
84
+ if (higherType instanceof z.ZodObject && lowerType instanceof z.ZodObject) {
85
+ const superTypeShape = higherType.shape;
86
+ const subTypeShape = lowerType.shape;
87
+ if (Object.keys(superTypeShape).length < Object.keys(subTypeShape).length)
88
+ return false;
89
+ for (const key in subTypeShape) {
90
+ if (!(key in superTypeShape)) return false;
91
+ if (!isCompatibleType(superTypeShape[key], subTypeShape[key], opts)) {
92
+ return false;
93
+ }
94
+ }
95
+ return true;
96
+ }
97
+
98
+ // ZodArray
99
+ if (higherType instanceof z.ZodArray && lowerType instanceof z.ZodArray) {
100
+ return isCompatibleType(higherType.element, lowerType.element, opts);
101
+ }
102
+
103
+ // ZodTuple
104
+ if (higherType instanceof z.ZodTuple && lowerType instanceof z.ZodTuple) {
105
+ if (higherType.items.length < lowerType.items.length) return false;
106
+ for (let i = 0; i < lowerType.items.length; i++) {
107
+ if (!isCompatibleType(higherType.items[i], lowerType.items[i], opts)) {
108
+ return false;
109
+ }
110
+ }
111
+ // Check rest
112
+ if (lowerType._def.rest) {
113
+ if (!higherType._def.rest) return false;
114
+ return isCompatibleType(higherType._def.rest, lowerType._def.rest, opts);
115
+ }
116
+ return true;
117
+ }
118
+
119
+ throw new Error(
120
+ "Failed to compare types!" +
121
+ higherType._def.typeName +
122
+ " " +
123
+ lowerType._def.typeName,
124
+ );
125
+ };
@@ -0,0 +1,208 @@
1
+ import type { EnumLike, ZodType } from "zod";
2
+ import { z } from "zod";
3
+ import {
4
+ type IsSameTypeOptions,
5
+ DEFAULT_COMPARE_TYPE_OPTIONS,
6
+ isPrimitiveType,
7
+ } from "./utils.ts";
8
+
9
+ /**
10
+ * isSameType is a function that checks if two ZodTypes are the same.
11
+ *
12
+ * Caveats:
13
+ * - The function does not validate specific criteria such as min or max values, length, email, etc.
14
+ * - It excludes comparisons involving methods like .describe(), .catch(), .default(), .refine(), and .transform().
15
+ * - When comparing definitions with .or and .and, they are assessed sequentially based on their order.
16
+ *
17
+ * @param a - The first ZodType to compare.
18
+ * @param b - The second ZodType to compare.
19
+ * @returns A boolean indicating whether the two types are the same.
20
+ *
21
+ * @throws Will throw an error if it encounters an unknown type.
22
+ *
23
+ * @example
24
+ * ```ts
25
+ * isSameType(z.string(), z.string()); // true
26
+ * isSameType(z.string(), z.number()); // false
27
+ * ```
28
+ */
29
+ export const isSameType = (
30
+ a: ZodType,
31
+ b: ZodType,
32
+ options?: Partial<IsSameTypeOptions>,
33
+ ): boolean => {
34
+ const opts = { ...DEFAULT_COMPARE_TYPE_OPTIONS, ...options };
35
+ const interceptorResult = opts.interceptor(a, b, opts);
36
+ if (interceptorResult === true || interceptorResult === false) {
37
+ return interceptorResult;
38
+ }
39
+
40
+ if (a === undefined || b === undefined) {
41
+ throw new Error("Failed to compare type! " + a + " " + b);
42
+ }
43
+
44
+ if (a === b) {
45
+ return true;
46
+ }
47
+
48
+ // compare constructor
49
+ if (a.constructor !== b.constructor) {
50
+ // https://stackoverflow.com/questions/24959862/how-to-tell-if-two-javascript-instances-are-of-the-same-class-type
51
+ return false;
52
+ }
53
+ // See https://github.com/colinhacks/zod/blob/master/src/types.ts
54
+ if (!("typeName" in a._def) || !("typeName" in b._def)) {
55
+ throw new Error("Failed to compare type! " + a._def + " " + b._def);
56
+ }
57
+ if (a._def.typeName !== b._def.typeName) {
58
+ return false;
59
+ }
60
+
61
+ // ZodBranded
62
+ if (opts.ignoreBranded) {
63
+ if (a instanceof z.ZodBranded) {
64
+ a = a.unwrap();
65
+ }
66
+ if (b instanceof z.ZodBranded) {
67
+ b = b.unwrap();
68
+ }
69
+ return isSameType(a, b, opts);
70
+ } else {
71
+ if (a instanceof z.ZodBranded || b instanceof z.ZodBranded) {
72
+ // We can not distinguish different branded type
73
+ // throw new Error("Can not distinguish different branded type!");
74
+ return false;
75
+ }
76
+ }
77
+
78
+ // ZodPromise ZodOptional ZodNullable ZodBranded
79
+ if ("unwrap" in a && typeof a.unwrap === "function") {
80
+ if (!("unwrap" in b && typeof b.unwrap === "function")) {
81
+ return false;
82
+ }
83
+ return isSameType(a.unwrap(), b.unwrap(), opts);
84
+ }
85
+
86
+ if (!opts.ignoreOptional && a.isOptional() !== b.isOptional()) return false;
87
+ if (!opts.ignoreNullable && a.isNullable() !== b.isNullable()) return false;
88
+
89
+ if (isPrimitiveType(a)) {
90
+ // Already assert a and b are the same constructor
91
+ return true;
92
+ }
93
+
94
+ // ZodObject
95
+ if (a instanceof z.ZodObject && b instanceof z.ZodObject) {
96
+ const aShape = a.shape;
97
+ const bShape = b.shape;
98
+ if (Object.keys(aShape).length !== Object.keys(bShape).length) return false;
99
+ for (const key in aShape) {
100
+ if (!(key in bShape)) return false;
101
+ if (!isSameType(aShape[key], bShape[key], opts)) return false;
102
+ }
103
+ return true;
104
+ }
105
+
106
+ // ZodArray
107
+ if (a instanceof z.ZodArray && b instanceof z.ZodArray) {
108
+ return isSameType(a.element, b.element, opts);
109
+ }
110
+
111
+ // ZodTuple
112
+ if (a instanceof z.ZodTuple && b instanceof z.ZodTuple) {
113
+ if (a.items.length !== b.items.length) return false;
114
+ for (let i = 0; i < a.items.length; i++) {
115
+ if (!isSameType(a.items[i], b.items[i], opts)) return false;
116
+ }
117
+ // Compare rest
118
+ if (a._def.rest || b._def.rest) {
119
+ // If one has rest, the other must have rest
120
+ if (!a._def.rest || !b._def.rest) return false;
121
+ return isSameType(a._def.rest, b._def.rest, opts);
122
+ }
123
+ return true;
124
+ }
125
+
126
+ // ZodLiteral
127
+ if (a instanceof z.ZodLiteral && b instanceof z.ZodLiteral) {
128
+ return a.value === b.value;
129
+ }
130
+
131
+ // ZodIntersection aka and
132
+ if (a instanceof z.ZodIntersection && b instanceof z.ZodIntersection) {
133
+ return (
134
+ isSameType(a._def.left, b._def.left, opts) &&
135
+ isSameType(a._def.right, b._def.right, opts)
136
+ );
137
+ }
138
+
139
+ // ZodUnion aka or
140
+ if (a instanceof z.ZodUnion && b instanceof z.ZodUnion) {
141
+ if (a.options.length !== b.options.length) return false;
142
+ for (let i = 0; i < a.options.length; i++) {
143
+ if (!isSameType(a.options[i], b.options[i], opts)) return false;
144
+ }
145
+ return true;
146
+ }
147
+
148
+ // ZodReadonly
149
+ if (a instanceof z.ZodReadonly && b instanceof z.ZodReadonly) {
150
+ return isSameType(a._def.innerType, b._def.innerType, opts);
151
+ }
152
+
153
+ // ZodRecord / ZodMap
154
+ if (
155
+ (a instanceof z.ZodRecord && b instanceof z.ZodRecord) ||
156
+ (a instanceof z.ZodMap && b instanceof z.ZodMap)
157
+ ) {
158
+ return (
159
+ isSameType(a.keySchema, b.keySchema, opts) &&
160
+ isSameType(a.valueSchema, b.valueSchema, opts)
161
+ );
162
+ }
163
+
164
+ // ZodSet
165
+ if (a instanceof z.ZodSet && b instanceof z.ZodSet) {
166
+ return isSameType(a._def.valueType, b._def.valueType, opts);
167
+ }
168
+
169
+ // ZodFunction
170
+ if (a instanceof z.ZodFunction && b instanceof z.ZodFunction) {
171
+ return (
172
+ isSameType(a.parameters(), b.parameters(), opts) &&
173
+ isSameType(a.returnType(), b.returnType(), opts)
174
+ );
175
+ }
176
+
177
+ // ZodEnum
178
+ if (a instanceof z.ZodEnum && b instanceof z.ZodEnum) {
179
+ const optionsA: [string, ...string[]] = a.options;
180
+ const optionsB: [string, ...string[]] = b.options;
181
+ if (optionsA.length !== optionsB.length) return false;
182
+ for (let i = 0; i < optionsA.length; i++) {
183
+ if (optionsA[i] !== optionsB[i]) return false;
184
+ }
185
+ return true;
186
+ }
187
+
188
+ // ZodNativeEnum
189
+ if (a instanceof z.ZodNativeEnum && b instanceof z.ZodNativeEnum) {
190
+ const enumA: EnumLike = a.enum;
191
+ const enumB: EnumLike = b.enum;
192
+ if (Object.keys(enumA).length !== Object.keys(enumB).length) return false;
193
+ for (const key in enumA) {
194
+ if (enumA[key] !== enumB[key]) return false;
195
+ }
196
+ return true;
197
+ }
198
+
199
+ // ZodLazy
200
+ // ZodEffects
201
+ // ZodDefault
202
+ // ZodCatch
203
+ // ZodPipeline
204
+ // ZodTransformer
205
+ // ZodError
206
+ console.error('Failed to compare type! "' + a, b);
207
+ throw new Error("Unknown type! " + a._def.typeName + " " + b._def.typeName);
208
+ };
package/src/utils.ts ADDED
@@ -0,0 +1,63 @@
1
+ import { z, type ZodType } from "zod";
2
+
3
+ export interface IsSameTypeOptions {
4
+ deep: true;
5
+ /**
6
+ * Ignore all specific validations like min, max, length, email etc.
7
+ *
8
+ * You still can use `interceptor` to validate the type manually.
9
+ */
10
+ ignoreValidations: true;
11
+ ignoreOptional: boolean;
12
+ ignoreNullable: boolean;
13
+ ignoreReadOnly: false;
14
+ ignoreBranded: boolean;
15
+ ignoreIntersectionsOrder: false;
16
+ /**
17
+ * A function that provides custom logic for comparing two ZodType instances.
18
+ *
19
+ * If the function returns `true` or `false`, the result will be used as the comparison result.
20
+ * Otherwise, the default comparison logic will be used.
21
+ *
22
+ */
23
+ interceptor: (
24
+ a: ZodType,
25
+ b: ZodType,
26
+ options: IsSameTypeOptions,
27
+ ) => boolean | void;
28
+ }
29
+
30
+ export interface IsCompatibleTypeOptions extends IsSameTypeOptions {
31
+ ignoreOptional: false;
32
+ ignoreNullable: false;
33
+ }
34
+
35
+ export const DEFAULT_COMPARE_TYPE_OPTIONS = {
36
+ deep: true,
37
+ ignoreOptional: false,
38
+ ignoreNullable: false,
39
+ ignoreReadOnly: false,
40
+ ignoreBranded: false,
41
+ ignoreValidations: true,
42
+ ignoreIntersectionsOrder: false,
43
+ interceptor: () => {},
44
+ } as const satisfies IsSameTypeOptions;
45
+
46
+ // See ZodFirstPartyTypeKind
47
+ export const isPrimitiveType = (a: ZodType): boolean => {
48
+ return (
49
+ a instanceof z.ZodString ||
50
+ a instanceof z.ZodNumber ||
51
+ a instanceof z.ZodNaN ||
52
+ a instanceof z.ZodBigInt ||
53
+ a instanceof z.ZodBoolean ||
54
+ a instanceof z.ZodDate ||
55
+ a instanceof z.ZodSymbol ||
56
+ a instanceof z.ZodUndefined ||
57
+ a instanceof z.ZodNull ||
58
+ a instanceof z.ZodAny ||
59
+ a instanceof z.ZodUnknown ||
60
+ a instanceof z.ZodNever ||
61
+ a instanceof z.ZodVoid
62
+ );
63
+ };