zod icon indicating copy to clipboard operation
zod copied to clipboard

Calling `isOptional()` on a `coerce.bigint` throws an error

Open marcus13371337 opened this issue 2 years ago • 6 comments

Try the following code:

const bigintSchema = z.coerce.bigint();
const isOptional = bigintSchema.isOptional();

That code should be able to run IMO, but now it throws an error, TypeError: Cannot convert undefined to a BigInt

marcus13371337 avatar Jan 19 '23 09:01 marcus13371337

Kind of related to the following: https://github.com/colinhacks/zod/discussions/1897 https://github.com/colinhacks/zod/discussions/1856

I can't really see the benefit of why Zod shouldn't catch these errors and handle them in the same way as you use to with most of the other errors that can occur. What are the drawbacks of having Zod a bit smarter and having this as the default implementation of coerce.bigint?

        try {
            return BigInt( value )
        } catch ( error ) {
            ctx.addIssue( {
                code: 'invalid_type',
                expected: 'unknown',
                received: value,
                message: `Can't be parsed to BigInt`,
            } )
        }

marcus13371337 avatar Jan 19 '23 10:01 marcus13371337

I added an easier way to work with coerce to my utilz library. Perhaps this will help you.

https://github.com/JacobWeisenburger/zod_utilz#coerce

import { zu } from 'zod_utilz'
const bigintSchema = zu.coerce( z.bigint() )
console.log( zu.SPR( bigintSchema.safeParse( undefined ) ).error?.issues )
// [
//     {
//       code: 'invalid_type',
//       expected: 'bigint',
//       received: 'undefined',
//       path: [],
//       message: 'Required'
//     }
// ]

const isOptional = bigintSchema.isOptional() // no ts error
console.log( isOptional ) // false, as expected

JacobWeisenburger avatar Jan 19 '23 16:01 JacobWeisenburger

@marcus13371337 Was my answer satisfactory? or would you like to leave this issue open as an enhancement request?

JacobWeisenburger avatar Jan 23 '23 02:01 JacobWeisenburger

Yes, I was able to get around the problem by creating a custom bigint-schema. But I don't see why zod, shouldn't be able to reply of a schema is optional without crashing (which happens to be a coerce bigint), to me that's clearly a bug

marcus13371337 avatar Jan 23 '23 07:01 marcus13371337

same about isNullable

const f = z.coerce.bigint();
f.isNullable();

despite the fact that .isNullable() calls .safeParse().

I think the confusion comes from the expectation that coerce is expected to be fail safe. However, it's not. In general, I don't like this feature. It brings more issues than benefits. CC @colinhacks

RobinTail avatar Apr 18 '23 19:04 RobinTail

looks like this issue will be fixed in Zod 4 — it does not throw in this case. Though, for z.coerce.bigint().isOptional() would return false, while z.coerce.boolean().isOptional() is true

RobinTail avatar Apr 27 '25 07:04 RobinTail