question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Feature request: First class string trimming support?

See original GitHub issue

Edit: 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:closed
  • Created 2 years ago
  • Reactions:11
  • Comments:5 (1 by maintainers)

github_iconTop GitHub Comments

14reactions
m-ruttercommented, Sep 29, 2021

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:

const trimString = (u: unknown) => typeof u === "string" ? u.trim() : u;

const schema = z.object({
  email: z.preprocess(trimString, z.string().email()),
})

0reactions
Zertzcommented, Mar 4, 2022

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:

const cleanString = z.preprocess((value) => {
  if (typeof value !== "string") {
    return value;
  }

  return value.trim().replace(/\s\s+/g, " ");
}, z.string());

You could even format phone numbers, validate that a given string looks like a date, and so on! 👌

Read more comments on GitHub >

github_iconTop Results From Across the Web

Can Jackson be configured to trim leading/trailing whitespace ...
My observation is that Jackson uses this deserializer for all strings. If the request class contains strings for boolean, etc, then having the...
Read more >
Prepare .NET libraries for trimming - Microsoft Learn
There are two ways to find trim warnings in your library: Enable project-specific trimming using the IsTrimmable property.
Read more >
Feature request: String interpolation - Change Proposals
You can write any interpolation function you want this way (for example, trimming and separating by spaces). You can add directives in the ......
Read more >
String.prototype.trimStart() - JavaScript - MDN Web Docs
The trimStart() method removes whitespace from the beginning of a string and returns a new string, without modifying the original string.
Read more >
Feature Toggles (aka Feature Flags) - Martin Fowler
"Feature Toggling" is a set of patterns which can help a team to deliver new ... You know this will require a fairly...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found