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.

Feature request: one of fields required

See original GitHub issue

If I am not mistaken right now you have to use refine and write your own logic to support such a feature. Zods goal is a nice developer experience and I think this would a good addition.

const schema = z.object({
  name: z.string().nonempty(),
  familyName: z.string().nonempty(),
  email: z.string().email(),
  phone: z.string(),
}).oneOf('email', 'phone')

This schema would only require nonempty email or phone.

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:11 (5 by maintainers)

github_iconTop GitHub Comments

1reaction
liamfdcommented, Sep 15, 2021

If I understand correctly, one downside of the refinement is that it doesn’t carry through to the type system, so TS won’t understand that exactly one of these keys has a value.

I know in TS you can express this “exactly one” requirement like:

type Person = {
  name: string;
  familyName: string;
} & (
  | { email: string; phone?: undefined }
  | { email?: undefined; phone: string }
);

(Which correctly requires exactly one of those two keys, lets you destructure, types result.email ?? result.phone as string instead of string | undefined, etc.)

Looks like you can more or less directly translate this to zod (which is awesome!):

  const base = z.strictObject({
    name: z.string(),
    familyName: z.string(),
  });
  const schema = z.union([
    base.merge(
      z.strictObject({ email: z.string(), phone: z.undefined().optional() })
    ),
    base.merge(
      z.strictObject({ email: z.undefined().optional(), phone: z.string() })
    ),
  ]);
  
  schema.parse({ name: 'a', familyName: 'b', email: 'c' }) // passes (good)
  schema.parse({ name: 'a', familyName: 'b', phone: 'd' }) // passes (good)
  schema.parse({ name: 'a', familyName: 'b', email: 'c', phone: 'd' }) // throws (good)
  schema.parse({ name: 'a', familyName: 'b' }) // throws (good)
  
  const result = schema.parse({...});
  const { email, phone } = result; // can destructure both 
 
  // this wouldn't work with the refinement because it doesn't carry through to the type, TS would see
  // this as string | undefined
  const contact: string = result.email ?? result.phone; // works

Not sure if there’s a more elegant way to do this, but it seems to be working. Also, I’m pretty sure this could be adapted to support “at least one of a or b” instead of “exactly one”.


Just thought I’d share in case anyone else comes across this issue trying to figure out how to get this working like I did.

1reaction
colinhackscommented, Nov 13, 2020

I think this is a nice idea but too niche to introduce into core. If people disagree feel free to comment and perhaps I’ll revisit this.

It’s easy enough to split out this logic in a reusable way.

const oneOf = (keys: string[]) => (val: any) => {
  for (const k of keys) {
    if (val[k] !== undefined) return true;
  }
  return false;
};

z.object({
  a: z.string(),
  b: z.string(),
}).refine(oneOf(['a', 'b']), 'Must have either a or b.');
Read more comments on GitHub >

github_iconTop Results From Across the Web

Feature Request: Required Fields for forms
So I created a form with some basic fields from a table. The form then has a button to submit the data and...
Read more >
How To Manage Feature Requests [Template included]
This guide will teach you everything you need to know about feature requests – how to process them, manage them, respond to them,...
Read more >
Feature Requests: How to Collect Them and Engage Users in ...
To do so, you should have one central location for collecting feedback from users. "We listen to our customers' feedback about what features...
Read more >
Feature Request Content - Instabug
When submitting a new feature request, users must fill out four fields. ... By default, a user's email address is required to submit...
Read more >
Feature Request: Add ability to define required/optional fields ...
I know this can be specified in the description, but it is not ideal. :) Here are the columns I am proposing for...
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