reactjstypescriptreact-hook-formzod

Zod Conditional Validation based on fetched data


I am fetching tsmin, tsmax values from get api. I have defined a zod schema with gte validation.

  const tsmin = Number(getMinMechProp("tensilestrength"));
  const tsmax = Number(getMaxMechProp("tensilestrength"));

 const mechPropSchema = z.object({
   tensilestrength: z.coerce.number()
      .gte(tsmin, `Value must be at least ${tsmin}`),
});

Now I want to apply zod lte validation only if tsmax > 0.

I didn't got the best way to achieve this


Solution

  • A zod schema is an ordinary object. You can use all the normal ways of choosing between objects.

    You can use an extra variable and a condition:

    let tsschema = z.coerce.number().gte(tsmin, `Value must be at least ${tsmin}`);
    if (tsmax > 0) {
        tsschema = tsschema.lte(tsmax, `Value must be at most ${tsmax}`);
    }
    const mechPropSchema = z.object({
        tensilestrength: tsschema,
    });
    

    You can use ?::

    const mechPropSchema = z.object({
        tensilestrength: (tsmax > 0) ? z.coerce.number().gte(tsmin, `Value must be at least ${tsmin}`).lte(tsmax, `Value must be at most ${tsmax}`) : z.coerce.number().gte(tsmin, `Value must be at least ${tsmin}`),
    });
    

    You can extract that to a function:

    function tsschema(tsmin, tsmax) {
        const schema = z.coerce.number().gte(tsmin, `Value must be at least ${tsmin}`);
        return (tsmax > 0) ? schema.lte(tsmax, `Value must be at most ${tsmax}`) : schema;
    }
    
    const mechPropSchema = z.object({
        tensilestrength: tsschema(tsmin, tsmax),
    });