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.

No .partial(), .deepPartial(), .merge() and others after using .refine() on ZodObject

See original GitHub issue

The refine method on a ZodObject instance returns a ZodEffects instance which lacks any of the object methods. It broke some code after migrating to v3. I don’t know the reasons behind this change, I guess it’s to support chaining multiple refine and transform calls, but maybe there’s a way to keep the original methods. It should also benefit another schema types’ methods.

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Comments:8 (1 by maintainers)

github_iconTop GitHub Comments

1reaction
scotttrinhcommented, Aug 20, 2021

I’ve already considered and tried the solution you suggested, but the derived userDataSchema (and others that are not included in the sample code) is used in a lot of places (within other intersections for ex.) and is very prone to error having to remember (or other devs having to guess) to add the refinement every time.

Yeah, I think the only way to avoid that is to use naming conventions and comments like:

// Note: this schema is unchecked for business logic refinement
export const unsafeCredentialDataSchema = z.object({
  // ...
});

export const credentialDataSchema = unsafeCredentialDataSchema.refine(usZipcodeRefinement);
1reaction
scotttrinhcommented, Aug 20, 2021

@kevlugli

Your example demonstrates the difficulty of a general solution. refine assumes that the input type is not-partial, so you would get runtime errors when trying to access undefined fields in your refinement function. Take this example given your schemas:

credentialEditionDataSchema.parse({
  firstName: "Scott",
  lastName: "Trinh",
  zipCode: "100001",
  birthday: new Date(2030, 0, 1),
});

In your particular refinement’s case, you’re testing data.countryId === "US" so you don’t fall into a runtime error, but imagine you wanted to normalize the string first like data.countryId.toUppercase() === "US", the compiler would not be able to tell you that it’s invalid since the type of data is not partial.

I know it’s annoying to have to respecify refinements, but I think if you end up transforming a type that you also need to refine, you’ll want to maybe share refinements that are defensive and applicable to all of the possible input values.

const usZipcodeRefinement = (data: { countryId?: string; zipCode?: string | null }) => {
  const isUs = data.countryId === 'US';
  const isEmpty = data.zipCode === undefined || data.zipCode === null;

  return !((isUs && isEmpty) || (!isUs && !isEmpty));
};

Then you can export an unrefined version that you can call .partial().refine(usZipcodeRefinement) on and a refined version that you can use on it’s own.

Read more comments on GitHub >

github_iconTop Results From Across the Web

RFC: Refactoring transformers and Zod 3 · Issue #264 - GitHub
If I do a merge() on two types I can still examine their shape. I'm using the library for both parsing and for...
Read more >
Untitled
For example, you can define a custom validation check on _any_ Zod schema with `.refine`: ```ts const myString = z.string().refine(val => val.length <=...
Read more >
zod - npm
Zod is a TypeScript-first schema declaration and validation library. I'm using the term "schema" to broadly refer to any data type/structure, from a...
Read more >
How to merge partial properties with the default values of a ...
Be aware of mutating references when merging objects like this. Both methods above will clone da and pa respectively to one level of...
Read more >
Designing the perfect Typescript schema validation library
When I started my quest to find the ideal schema declaration/validation library, I assumed the ... and merge them with t.intersection() .
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