Closed mayorandrew closed 1 year ago
I agree that transform should have the option to emit errors. Right now I have to basically run the same quote twice, first in a refinement and then again in the transform. E.g. to get a DecimalJs value:
z.string()
.refine(value => {
try { new DecimalJs(value) } catch { return false; }
return true;
})
.transform(value => new DecimalJs(value));
It would be ideal if the transform function would be allowed to throw exceptions, and either use the exception message as error, or optionally to pass a secondary argument to the transform function which then will be used as value.
Thus the above code could be represented instead as:
z.string().transform(value => new DecimalJs(value), 'Invalid decimal');
Right now I have to basically run the same quote twice, first in a refinement and then again in the transform
@DASPRiD in the latest versions of zod you don't have to do this twice because transform
provides the ctx
argument:
z.string()
.transform((value, ctx) => {
try {
return new DecimalJs(value);
} catch (error) {
ctx.addIssue({
fatal: true,
code: ZodIssueCode.custom,
message: error.message,
params: { ...error, name: error.name }
})
}
// This is a hack to get proper type inference
return undefined as unknown as DecimalJs;
});
Nevertheless, having native support for throws in transform would make the syntax much simpler.
// This is a hack to get proper type inference return undefined as unknown as DecimalJs;
I see we can now return z.NEVER
to avoid the casting hack.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
README says that
transform
should not throw errors. This makes it less convenient to use for two reasons:ctx.addIssue
calls withfatal: true
For example, I wrote this utility helper in my applicaiton to handle this problem:
I use it like this:
Although this helper solves the problem for me, it would be nice if something like this could be included in zod itself. If catching all errors is too much (it would likely be a breaking change), maybe it can only catch instances of a specific error class. That would still be beneficial because it would eliminate the need for a return type hack.