Search code examples
typescriptzod

Recursively remove property from Zod object


With a complex Zod object, I would like to recursively search for a property someProp and remove it wherever it exists, possibly using .omit({ someProp: true }). Here is an attempt that does not work...

function removeSomeProp<T extends ZodRawShape>(obj: T): T {
  const result: any = {};

  Object.keys(obj).forEach((key) => {
    const value = obj[key];

    if (value instanceof ZodObject) {
      result[key] = removeSomeProp(value.shape);
    } else {
      result[key] = value;
    }
  });

  return z.object(result).omit({ someProp: true }) as unknown as T;
}


Solution

  • Here is the solution I came up with... Note that once it find a someProp property, it no longer recurses down that branch. This also makes a few assumptions about the shape of the ZodObject.

    function removeSomeProp(schema: ZodTypeAny): ZodTypeAny {
      if (schema instanceof ZodObject) {
        if (schema.shape["someProp" as keyof typeof schema.shape]) {
          return schema.omit({ someProp: true });
        }
    
        const newObj: any = {};
        Object.keys(schema.shape).forEach((key) => {
          newObj[key as keyof typeof newObj] = removeSomeProp(schema.shape[key as keyof typeof schema.shape]);
        });
        return z.object(newObj);
      }
      if (schema instanceof ZodOptional) {
        // eslint-disable-next-line no-underscore-dangle
        return removeSomeProp(schema._def.innerType);
      }
      if (schema instanceof ZodArray) {
        return removeSomeProp(schema.element);
      }
    
      return schema;
    }