Feature request: First class string trimming support?
See original GitHub issueEdit: I’ve since changed my mind, but leaving open to allow discussion.
I suppose this feature request is also a question about how the maintainers view the library in terms of its usage in form validation.
A very common use case when dealing with user input in forms is you need to ignore/strip whitespace. " "
or "michael@example.com "
isn’t valid input in some cases, and using .min(1)
or .email()
respectively will get what might be seen by some as the wrong result. In those cases you want to parse or validate the input after stripping the whitespace, and also transform the input to strip it out altogether in the ouput.
This question was raised in https://github.com/colinhacks/zod/issues/614, and preprocess
was suggeted. The solution using preprocess
presumably goes a follows:
z.preprocess((arg) => typeof arg === "string" ? arg.trim() : arg, z.string().min(1)).parse(" "); // throws
z.preprocess((arg) => typeof arg === "string" ? arg.trim() : arg, z.email()).parse("michael@example.com "); // ouput: "michael@example.com"
Now this seems quite verbose and you are having to validate the arg
value ahead of your processing step (kind of the purpose of zod in the first place - to validate that something is a string etc…), and other libraries such as yup
have builtin trim methods that will transform the input ahead of validation as a builtin operation:
Yup.string().trim().min(1).validateSync(" ") // ValidationError "this must be at least 1 characters"
My sense is zod
wants there to be a strong seperation between transformation and parsing. Is there space for zod having better support for what appears to be a pretty common use case? Something along the lines of:
// transforms after checking that input is a string
z.string().trim().min(1).parse(" ") // throws
z.string().trim().email().parse("michael@example.com ") // ouput: "michael@example.com"
// or does not change output, and force you to add a transform if you want the parsed ouput to have whitespace stripped
z.string().trim().min(1).transform(str => str.trim()).parse(" ") // throws
z.string().trim().email().transform(str => str.trim()).parse("michael@example.com ") // ouput: "michael@example.com"
The latter case is still a little noisy and confusing, but at least I’m dealing with a string by this point instead of an unknown
because it has already passed parsing as a string.
Does this fit into zod
’s vision (I’m guessing that it might not)?
Issue Analytics
- State:
- Created 2 years ago
- Reactions:11
- Comments:5 (1 by maintainers)
Top GitHub Comments
Having used zod more I appreciate the the purity of the current implementation with its strict separation between validation and mutation/effects, and I’m thinking that adding a preprocess trim string function isn’t really the end of the world.
I guess my personal preference is to not add this trimming feature, but I’m going to leave this open mainly so others have an opportunity to discuss it or a maintainer to respond.
I’m personally fine with living with this and keeping the original philosophy:
I’m with @m-rutter here,
preprocess
definitely seems like the way to go, especially that you can perform very powerful transformations. In many cases, trimming the string is not quite enough and I end up having to do extra work anyway. For example, here I also replace multiple consecutive space characters with a single space:You could even format phone numbers, validate that a given string looks like a date, and so on! 👌