-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Throwing errors in preprocess #696
Comments
[Deleted for privacy reasons] |
The few times I've played around with // Query parameter schema
const loose = z.object({
aBoolean: z.string().transform(Boolean),
aNumber: z.string().transform(Number),
});
// Domain schema
const query = z.object({
aBoolean: z.boolean(),
aNumber: z.number(),
});
const fromQueryParams = z.preprocess(
loose.parse,
query
); I have to admit that I haven't used |
Perhaps you should be able to add issues inside |
+1 for adding issues in IMO this would make it much more straightforward to build a reusable set of "lenient preprocessors" on top of zod (#804 #1019), while keeping good error messages. I currently work around it with something like this: function maybeParseNumber(v: unknown): unknown | number {
if (typeof v !== "string") {
return v;
}
if (!v) {
return v; // Otherwise "" is parsed as 0
}
const ret = Number(v);
return isNaN(ret) ? v : ret;
}
// Preprocessors for stringly-typed data.
const zs = {
number: (augment?: (s: ZodNumber) => ZodNumber) => {
let schema = z.number({ invalid_type_error: "Not a number", required_error: "Required" });
schema = augment ? augment(schema) : schema;
return z.preprocess((v) => maybeParseNumber(v), schema);
},
} Notice that:
Consequently, the only way to allow adding constraints on the inner zs.number((s) => s.min(5).max(10)) Unfortunately, this means that I can't simply stick a pre-existing number schema into a lenient schema. For instance, I'd like to be able to do: const age = z.number().lte(5, { message: "this👏is👏too👏big" });
const queryParams = z.object({
age: zs.number(age)
}) Or even just take a full "strict schema" and automatically loosen it recursively (similar to what znv does), e.g.: // age is defined as above
const CreatePerson = z.object({
age: age
});
const CreatePersonLenient = lenient(CreatePerson);
CreatePersonLenient.parse(...); |
Couldn't the same be said for a transform you want to validate? |
Took a stab at the PR for transform(). Wouldn't be hard to do for preprocess? #1056 |
@morgs32 I could be wrong, but I doubt adding issues inside |
Well @selimb this would not break from the idea that a transform would ONLY operate on valid data that has been "refined" before it. Let's consider this note from the README on
What if you are doing a transform that might not work? We shouldn't have to look far for a transform that might NOT work. For example, from the README on async-transforms:
If you wrote this - hopefully your PR reviewer says, "what if
You know what else smells? You don't have access to Thoughts?? @colinhacks whaddya think? |
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. |
@scotttrinh same stuff then inside #330, all of this is actually only OK with Your — elegant, I admit — example :
actually throws on
Of course
is not an option because preprocess is not intendented to work like this, and
leave me in a doubt of what to do on I think in that last case, |
@scotttrinh I think I found a solution, less elegant but working apparently. import { z, ZodType } from 'zod'
const stringToNumberSchema = (def: number) => (z.string().default(`${def}`).transform(Number))
const safePreprocessor = <O, Z extends ZodType<O>> (preprocessorSchema: Z) => (val: unknown): O | null => {
const parsed = preprocessorSchema.safeParse(val)
if (!parsed.success) {
return null
}
return parsed.data
}
const _paginationSchema = z.object({
skip: z.preprocess(
safePreprocessor(stringToNumberSchema(0)),
z.number().min(0)
),
limit: z.preprocess(
safePreprocessor(stringToNumberSchema(20)),
z.number().min(0).max(100)
)
}).strict()
export type PaginationQuery = z.infer<typeof _paginationSchema> Can I have your thoughts ? |
@colinhacks are you still considering this? |
[Deleted for privacy reasons]
The text was updated successfully, but these errors were encountered: