Preprocess (refine/transform) -> refine.transform.pipe

Here a slightly different suggestion: You could use a z.string().refine().transform().pipe(z.object({})) to make it a little more declarative and to rely on the Zod error reporting features in your "preprocessing" part.
3 Replies
Scott Trinh
Scott TrinhOP2y ago
One potential caveat is that errors in piped schemas get reported for each schema in order, so you wouldn't get the int/min/max errors until the string was properly formatted.
addamsson
addamsson2y ago
do you mean something like this?
const timeOfDayT = z
.string()
.superRefine((value, ctx) => {
if (value.includes(":") === false) {
ctx.addIssue(wrongFormatIssue);
return;
}
const [hoursStr, minsStr] = value.split(":");
if (!hoursStr || !minsStr) {
ctx.addIssue(wrongFormatIssue);
return;
}
const hours = parseInt(hoursStr);
const mins = parseInt(minsStr);
if (isNaN(hours) || isNaN(mins)) {
ctx.addIssue(wrongFormatIssue);
}
})
.transform((value) => {
const [hoursStr, minsStr] = value.split(":");
const hours = parseInt(hoursStr!);
const mins = parseInt(minsStr!);
return {
hours,
mins,
};
});
const timeOfDayT = z
.string()
.superRefine((value, ctx) => {
if (value.includes(":") === false) {
ctx.addIssue(wrongFormatIssue);
return;
}
const [hoursStr, minsStr] = value.split(":");
if (!hoursStr || !minsStr) {
ctx.addIssue(wrongFormatIssue);
return;
}
const hours = parseInt(hoursStr);
const mins = parseInt(minsStr);
if (isNaN(hours) || isNaN(mins)) {
ctx.addIssue(wrongFormatIssue);
}
})
.transform((value) => {
const [hoursStr, minsStr] = value.split(":");
const hours = parseInt(hoursStr!);
const mins = parseInt(minsStr!);
return {
hours,
mins,
};
});
i'm not sure I understand what pipe() does though oh i understand that's it, right?
const timeOfDayT = z
.string()
.superRefine((value, ctx) => {
if (value.includes(":") === false) {
ctx.addIssue(wrongFormatIssue);
return;
}
const [hoursStr, minsStr] = value.split(":");
if (!hoursStr || !minsStr) {
ctx.addIssue(wrongFormatIssue);
return;
}
const hours = parseInt(hoursStr);
const mins = parseInt(minsStr);
if (isNaN(hours) || isNaN(mins)) {
ctx.addIssue(wrongFormatIssue);
}
})
.transform((value) => {
const [hoursStr, minsStr] = value.split(":");
const hours = parseInt(hoursStr!);
const mins = parseInt(minsStr!);
return {
hours,
mins,
};
})
.pipe(
z.object({
hours: z.number().int().min(0).max(23),
mins: z.number().int().min(0).max(59),
})
);
const timeOfDayT = z
.string()
.superRefine((value, ctx) => {
if (value.includes(":") === false) {
ctx.addIssue(wrongFormatIssue);
return;
}
const [hoursStr, minsStr] = value.split(":");
if (!hoursStr || !minsStr) {
ctx.addIssue(wrongFormatIssue);
return;
}
const hours = parseInt(hoursStr);
const mins = parseInt(minsStr);
if (isNaN(hours) || isNaN(mins)) {
ctx.addIssue(wrongFormatIssue);
}
})
.transform((value) => {
const [hoursStr, minsStr] = value.split(":");
const hours = parseInt(hoursStr!);
const mins = parseInt(minsStr!);
return {
hours,
mins,
};
})
.pipe(
z.object({
hours: z.number().int().min(0).max(23),
mins: z.number().int().min(0).max(59),
})
);
Scott Trinh
Scott TrinhOP2y ago
Exactly. You can move your min/max checking into your superRefine and then you don't even really need the z.object, but depending on your use case, it's nice to have the z.object for other things.
Want results from more Discord servers?
Add your server