coerce.boolean incorrect #3329
-
import { z } from 'zod';
const schema = z.object({
something: z.coerce.boolean(),
});
console.log(schema.parse({ something: 'false' })); expected:
got:
|
Beta Was this translation helpful? Give feedback.
Replies: 10 comments 2 replies
-
Hello ! No, this behavior is normal. You can verify it by executing this code: console.log(Boolean("false")); // displays true You can do something like that: const booleanStringSchema = z.string().transform(value => {
if (value === "true") {
return true;
} else if (value === "false") {
return false;
} else {
throw new Error("The string must be 'true' or 'false'");
}
}); Regards. |
Beta Was this translation helpful? Give feedback.
-
I believe it's incorrect. Coercion should convert the string into the desired type. For example, coercing a boolean string 'false' should result in false, which is the expected behavior. |
Beta Was this translation helpful? Give feedback.
-
No, you are wrong. Go read the documentation: https://zod.dev/?id=coercion-for-primitives This is exactly what I explained to you. If you find these rules illogical, go blame javascript specification writers. ;) Regards. |
Beta Was this translation helpful? Give feedback.
-
I agree that the js spec is weird but do think one would assume coerce of string value true|false to work. Pretty common to use booleans in forms which transmit as strings but we want them to be proper booleans for the database. Transfrom didn't work for me in this use case but preprocess did like so:
The first conditional is needed because the types are checked on their way out of the database and have the boolean type. |
Beta Was this translation helpful? Give feedback.
-
Personally, I don't find these coercions rules weird. |
Beta Was this translation helpful? Give feedback.
-
@vtgn got me thinking and I was reviewing my giant diff with other changes this am. Decided only returning a value on boolean type or string value of "true" or "false". Anything else should throw the error like this.
|
Beta Was this translation helpful? Give feedback.
-
Also worth mentioning existing db values may be undefined. For my use case I just default it to true by adding || value === undefined to the value equal string true line. More important is an error here is an app error. You'll likely still want a validator with a nice user error message that ideally they will never encounter. |
Beta Was this translation helpful? Give feedback.
-
Also found this confusing. Perhaps would be nice if the API let you swap between two methods of coercion (intuitive and native). Intuitively I'd expect this API to convert "false" into a false boolean since most of the time I think that's what people would require. In my example I've using Zod to parse querystring values and for a boolean I'm using true/false strings. Something like: |
Beta Was this translation helpful? Give feedback.
-
I find this highly problematic, too. When used for parameter validation on a GET request, we only have strings. So, it will always be In order to validate that, we want the string to be a boolean. is there an option to JSON.parse prior first? |
Beta Was this translation helpful? Give feedback.
-
Going to close this discussion as "works as intended" and furthermore, the documentation specifically calls out this case and provides some guidance on what to do if the default behavior does not work for you. TL;DR: do not treat As a side note: I don't want to come off as dismissive of the pain here: parsing stringy APIs like query parameters and form data is a difficult problem and there are few tools out that that really help. Zod will probably be part of a general solution that someone will eventually build, but the behavior of Zod specifically is designed to match TypeScript's type system and JavaScript's runtime, so we inherit the quirks involved here. |
Beta Was this translation helpful? Give feedback.
No, you are wrong.
This is normal that coerce method uses the standard javascript conversions rules.
Go read the documentation: https://zod.dev/?id=coercion-for-primitives
Particularly this part:
This is exactly what I explained to you.
If you find these rules illogical, go blame javascript specification writers. ;)
But if you want different conversion rules, you'll have to implement them yourself like in my previous example.
Regards.