Replies: 7 comments 15 replies
-
you could make a recursive function that would get the keys from |
Beta Was this translation helpful? Give feedback.
-
// get zod object keys recursively
const zodKeys = <T extends z.ZodTypeAny>(schema: T): string[] => {
// make sure schema is not null or undefined
if (schema === null || schema === undefined) return [];
// check if schema is nullable or optional
if (schema instanceof z.ZodNullable || schema instanceof z.ZodOptional) return zodKeys(schema.unwrap());
// check if schema is an array
if (schema instanceof z.ZodArray) return zodKeys(schema.element);
// check if schema is an object
if (schema instanceof z.ZodObject) {
// get key/value pairs from schema
const entries = Object.entries(schema.shape);
// loop through key/value pairs
return entries.flatMap(([key, value]) => {
// get nested keys
const nested = value instanceof z.ZodType ? zodKeys(value).map(subKey => `${key}.${subKey}`) : [];
// return nested keys
return nested.length ? nested : key;
});
}
// return empty array
return [];
}; The code above can handle See @kimmobrunfeldt's response for more info. |
Beta Was this translation helpful? Give feedback.
-
Hey guys, i just created a library for this: |
Beta Was this translation helpful? Give feedback.
-
Sheesh man, I was just thinking about this last night. |
Beta Was this translation helpful? Give feedback.
-
Why not have the built-in parser do the work for us... Simplest solution for extracting the keys of a flat zod schema:import type { ZodSchema } from 'zod';
export function getZodSchemaFieldsShallow(schema: ZodSchema) {
const fields: Record<string, true> = {};
const proxy = new Proxy(fields, {
get(_, key) {
if (key === 'then' || typeof key !== 'string') {
return;
}
fields[key] = true;
},
});
schema.safeParse(proxy);
return fields;
} With nesting:import type { ZodSchema } from 'zod';
type ZodSchemaFields = { [K: string]: ZodSchemaFields | true };
type DirtyZodSchemaFields = { [K: string]: DirtyZodSchemaFields };
const _proxyHandler = {
get(fields: DirtyZodSchemaFields, key: string | symbol) {
if (key === 'then' || typeof key !== 'string') {
return;
}
if (!fields[key]) {
fields[key] = new Proxy({}, _proxyHandler);
}
return fields[key];
},
};
function _clean(fields: DirtyZodSchemaFields) {
const cleaned: ZodSchemaFields = {};
Object.keys(fields).forEach((k) => {
const val = fields[k];
cleaned[k] = Object.keys(val).length ? _clean(val) : true;
});
return cleaned;
}
export function getZodSchemaFields(schema: ZodSchema): ZodSchemaFields {
const fields = {};
schema.safeParse(new Proxy(fields, _proxyHandler));
return _clean(fields);
} Only thing is, you can't have any keys named |
Beta Was this translation helpful? Give feedback.
-
FWIW, I did not need the recursion but my search engine still took me to this discussion... for the reference, here is what I came up with. It's simple enough that I thought it was worth mentionning it: const keys = [...schema.keyof().options] It seems to work. |
Beta Was this translation helpful? Give feedback.
-
Just in case anyone is searching for the same thing, I had a use case to do a deep dive on dirty fields where some of which resided behind some discriminated unions. Please see my below solution to parse the Zod schema keys including some dedupe caused by common discriminated union fields.
|
Beta Was this translation helpful? Give feedback.
-
I checked the docs but couldn't find a way to do something like the pseudo-code below...
Any suggestions?
Beta Was this translation helpful? Give feedback.
All reactions