Z
Zod•5w ago
unnreaal

unnreaal - tsconst schema = z.coerce.string()....

const schema = z.coerce.string().optional();

// type Schema = string | undefined;
type Schema = z.infer<typeof schema>;
const schema = z.coerce.string().optional();

// type Schema = string | undefined;
type Schema = z.infer<typeof schema>;
But z.coerce.string() will always cast the value to a string, why not just string instead of string | undefined?
24 Replies
Scott Trinh
Scott Trinh•5w ago
Infer is the input type. z.output gives the output type
unnreaal
unnreaalOP•5w ago
still the same with z.output
Scott Trinh
Scott Trinh•5w ago
Oh yeah, I guess it would be that type. Optional doesn't make sense here since coerce swallows undefined. 🤔
unnreaal
unnreaalOP•5w ago
its a type error no?
Scott Trinh
Scott Trinh•5w ago
Well... sure, I could see that, but really optional and nullable are just not really meaningful for coerce types. Same for union, really Is there something specific you're intending to mean by making it optional? It already accepts undefined as an input.
unnreaal
unnreaalOP•5w ago
no, i mean that the type (z.output) is wrong
Scott Trinh
Scott Trinh•5w ago
It's only wrong because .optional makes everything | undefined, but optional doesn't mean anything for z.coerce schemas, so it's "right" but only technically right.
unnreaal
unnreaalOP•5w ago
yes bro, i know the | undefined doesn't mean anything for z.coerce schemas i mean that the type is completely wrong
Scott Trinh
Scott Trinh•5w ago
for instance, this is also supported, but doesn't work:
const schema = z.union([z.coerce.string(), z.coerce.number()]);
type Schema = z.output<typeof schema>;
// string | number
const schema = z.union([z.coerce.string(), z.coerce.number()]);
type Schema = z.output<typeof schema>;
// string | number
In actuality, it's always string at runtime.
unnreaal
unnreaalOP•5w ago
const user = z.object({
name: z.coerce.string().optional(),
});

// { name: string | undefined; }
type User = z.output<user>;
const user = z.object({
name: z.coerce.string().optional(),
});

// { name: string | undefined; }
type User = z.output<user>;
Scott Trinh
Scott Trinh•5w ago
I mean that .optional should not be an option for coerce schemas.
unnreaal
unnreaalOP•5w ago
but the name is always a string here so zod should throw an error warning the optional can not (or is unnecessary) be used with coerce schemas
Scott Trinh
Scott Trinh•5w ago
Nope: this is { name: string; }
Scott Trinh
Scott Trinh•5w ago
it should just not allow you to .optional() on a coerce schema.
unnreaal
unnreaalOP•5w ago
nop im sure it isnt it is { name?: string | undefined; } try yourself
Scott Trinh
Scott Trinh•5w ago
no, your original (without the .optional) is string
unnreaal
unnreaalOP•5w ago
bro, i edited the message (before you send the playground link)
Scott Trinh
Scott Trinh•5w ago
yep! don't use optional for coerce schemas.
unnreaal
unnreaalOP•5w ago
zod should throw an error or at least warn users
Scott Trinh
Scott Trinh•5w ago
yes it should just not include an .optional method. but it does for now, so just avoid it until we fix that.
unnreaal
unnreaalOP•5w ago
.optional is in ZodType, no?
Scott Trinh
Scott Trinh•5w ago
it is! we'll need to fix that. in the meantime, do not: 1. Use optional, nullish, or nullable with z.coerce schemas 2. Use z.coerce schemas in a z.union 3. Probably other stuff.
Scott Trinh
Scott Trinh•5w ago
GitHub
We should not allow optional, nullish, or nullable on `z.coer...
Since z.coerce.* schemas will always return the primitive, even if you pass undefined or null, we should disallow this. Also, things like z.union([z.coerce.string(), z.coerce.number()]) will always...
Want results from more Discord servers?
Add your server