Z
Zod•6mo ago
janglad

janglad - Okay another question 😅 Why does t...

Okay another question 😅 Why does this return a ZodEffect with a possible unnkown?
export const defAString = z.preprocess(
(val) => "this is def a string",
z.string(),
);
// const defAString: z.ZodEffects<z.ZodString, string, unknown>
export const defAString = z.preprocess(
(val) => "this is def a string",
z.string(),
);
// const defAString: z.ZodEffects<z.ZodString, string, unknown>
18 Replies
Scott Trinh
Scott Trinh•6mo ago
I don't remember the signature there but I think that is the input type, which makes sense for preprocess
janglad
janglad•6mo ago
ooh huh yes you're right
janglad
janglad•6mo ago
this does indeed work as expected
export const stringOrEmptyToNull = z.preprocess(
(val) => (val && typeof val === "string" ? val : null),
z.string().nullable()
)
// as z.ZodEffects<z.ZodNullable<z.ZodString>, string | null>;
// TODO: check above

const test = stringOrEmptyToNull.parse("test");
// const test: string | null
export const stringOrEmptyToNull = z.preprocess(
(val) => (val && typeof val === "string" ? val : null),
z.string().nullable()
)
// as z.ZodEffects<z.ZodNullable<z.ZodString>, string | null>;
// TODO: check above

const test = stringOrEmptyToNull.parse("test");
// const test: string | null
altho somehow it does show up as unknown here, which is fixed by using that as that is commented right now
No description
Scott Trinh
Scott Trinh•6mo ago
Yeah the output type is string so the type of the parsed value is string Every schema has an input and output type
janglad
janglad•6mo ago
oohhh yeah I am indeed using z.input hmm this is somewhat annoying lol cause IIRC I do need to do that as there are also transforms but then I'd need the output of that preprocess specifically 😄 altho actually no using z.output it still shows up as unknown there the schema setup is a bit complex so I'll need to do some digging as to where that's happening
Scott Trinh
Scott Trinh•6mo ago
What's the schema for street here?
janglad
janglad•6mo ago
that stringOrEmptyToNull but yes in the end it is indeed caused by using z.input which makes sense, output was just giving a different error which also makes sense but I guess I can just lie to TS here and use the as
Scott Trinh
Scott Trinh•6mo ago
Are you trying to construct a value and using the type as a type annotation without parsing it?
janglad
janglad•6mo ago
It's being used like this
const emptyForm = generateEmptyForm(user);

const defaultValues = create
? emptyForm
:
transFormListing(props.defaultValues, user);

const formSchema = create
? createListingInputSchema
: updateListingInputSchema;

type FormType = z.input<typeof formSchema>;

const form = useForm<FormType>({
defaultValues,
resolver: zodResolver(formSchema),
reValidateMode: "onSubmit",
});
const emptyForm = generateEmptyForm(user);

const defaultValues = create
? emptyForm
:
transFormListing(props.defaultValues, user);

const formSchema = create
? createListingInputSchema
: updateListingInputSchema;

type FormType = z.input<typeof formSchema>;

const form = useForm<FormType>({
defaultValues,
resolver: zodResolver(formSchema),
reValidateMode: "onSubmit",
});
Scott Trinh
Scott Trinh•6mo ago
Ahhh. Right. I wonder if instead of preprocess you should have a transform that checks for the empty string so that the input and output type is string | null still 🤔
janglad
janglad•6mo ago
that's not really ideal either. RHF sends an empty input as an empty string, if I then want to add on things like a min length I wouldn't be able to do say z.string().min(5).nullable().transform(emptyToNull) as when you pass it an empty string it complains about not being 5 long and while I can check for that in a refine, those only get triggered after all the other fields are valid so that's not great UX eitherr mind you I can't chain the min and such now either with the predefined variable but it is possible to do in a preprocess
Scott Trinh
Scott Trinh•6mo ago
z.union([
z.literal("").transform(() => null),
z.string().min(5).nullable(),
]);
z.union([
z.literal("").transform(() => null),
z.string().min(5).nullable(),
]);
You could do something like that maybe? Or:
z.string().transform((s) => s || null).pipe(
z.string().min(5).nullable()
);
z.string().transform((s) => s || null).pipe(
z.string().min(5).nullable()
);
janglad
janglad•6mo ago
second one would still have the issue of only validating after all the rest right but I had not thought of the first! that might actually be the most elegant solutioN!
Scott Trinh
Scott Trinh•6mo ago
I'm not sure what you mean here?
janglad
janglad•6mo ago
transforms and refines only run once other fields are valid right
Scott Trinh
Scott Trinh•6mo ago
It will be run in this case as long as it's a string maybe you're thinking about refines/transforms on an object (which requires that all of the properties pass their validations)?
janglad
janglad•6mo ago
yes I am indeed 😄
Scott Trinh
Scott Trinh•6mo ago
fwiw, I find the pipe implementation to be a bit more "accurate" to what you're trying to achieve in mapping an empty string to null and then adding addtional string constraints on any remaining strings, but both seem pretty readable. fwiw, i feel like these days pipe and coerce pretty much replace most use cases for preprocess.
Want results from more Discord servers?
Add your server
More Posts
janglad - Am I missing something or is it not p...Am I missing something or is it not possible to make a primitive required? I have a use case where OMB - hmm... I know this issue was closed way b...hmm... I know this issue was closed way back, but why does this work ```const passwordSchema = z.objpanda - how would i go about validating a datab...how would i go about validating a database column that is typed as JSON and can have any amount of vaddamsson - Is there a way to fine-tune error m...Is there a way to fine-tune error messages in Zod to include the path (or the last element of the paaddamsson - I have the following code:tsimpor...I have the following code: ```ts import { z } from "zod"; const Address = z.object({ street: z.janglad - Quick question, .pick allows non exis...Quick question, `.pick` allows non existing keys. Is this supposed to be the case and am I missing sYamereee - 👋 Hello Zod Wizards! A Question wh...👋 Hello Zod Wizards! A Question when using coerce with my API responses, I have a schema here Notaddamsson - Hi everyone! 👋 I have a small prob...Hi everyone! 👋 I have a small problem with Zod. In my code: ```ts z .string() .superRefine(David Tejada - Hi. I have the following functio...Hi. I have the following function which I have simplified for the example. The type Storage is inferKas.st - Hi everyone, I have a schema with an e...Hi everyone, I have a schema with an enum: ```javascript const schema = z.object({ foo: z.enum(["f