Replies: 6 comments 14 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.
-
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