Skip to content

Commit 67c88a3

Browse files
committed
refactor: add isZodV3Type
1 parent e6540a5 commit 67c88a3

File tree

2 files changed

+39
-2
lines changed

2 files changed

+39
-2
lines changed

src/__tests__/zod4.test.ts

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1+
/* eslint-disable @typescript-eslint/no-require-imports */
12
import { describe, expect, expectTypeOf, it, test } from 'vitest';
23
import { z as z3 } from 'zod/v3';
34
import { z as z4 } from 'zod/v4';
45

5-
import { isZodTypeLike } from '../zod4.js';
6+
import { isZodTypeLike, isZodV3Type } from '../zod4.js';
67

78
import type {
89
ZodErrorLike,
@@ -69,3 +70,29 @@ describe('isZodTypeLike', () => {
6970
expect(isZodTypeLike({ '~standard': { vendor: 'DNP' } })).toBe(false);
7071
});
7172
});
73+
74+
describe('isZodV3Type', () => {
75+
// since we use require here, the prototype chain in the cjs module will be different than the esm build
76+
const { z: z3_2 } = require('zod/v3') as typeof import('zod/v3');
77+
78+
it('should return true for an instance of ZodNumber', () => {
79+
expect(isZodV3Type(z3.number())).toBe(true);
80+
});
81+
it('should return true for an instance of ZodObject', () => {
82+
expect(isZodV3Type(z3.object({}))).toBe(true);
83+
});
84+
it('should return false for null', () => {
85+
expect(isZodV3Type(null)).toBe(false);
86+
});
87+
it('should return false for any empty object', () => {
88+
expect(isZodV3Type({})).toBe(false);
89+
});
90+
it('should return false for an object with a null prototype', () => {
91+
expect(isZodV3Type(Object.create(null))).toBe(false);
92+
});
93+
it('should return true for a ZodObject created in a different context', () => {
94+
const input = z3_2.object({});
95+
expect(input).not.toBeInstanceOf(z3.ZodType);
96+
expect(isZodV3Type(input)).toBe(true);
97+
});
98+
});

src/zod4.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
import { isObjectLike, isPlainObject } from './object.js';
1+
import type { z as z3 } from 'zod/v3';
2+
3+
import { isObject, isObjectLike, isPlainObject } from './object.js';
24

35
export type ZodIssueLike = {
46
[key: string]: any;
@@ -44,3 +46,11 @@ export function isZodTypeLike(arg: unknown): arg is ZodTypeLike<unknown> {
4446
const standardSchema: unknown = Reflect.get(arg, '~standard');
4547
return isPlainObject(standardSchema) && standardSchema.vendor === 'zod';
4648
}
49+
50+
export function isZodV3Type(arg: unknown): arg is z3.ZodTypeAny {
51+
let prototype: null | object = null;
52+
if (isObject(arg) && isObject(arg.constructor)) {
53+
prototype = Reflect.getPrototypeOf(arg.constructor);
54+
}
55+
return Boolean(prototype && Reflect.get(prototype, 'name') === 'ZodType');
56+
}

0 commit comments

Comments
 (0)