简体   繁体   中英

Zod Schema: How to make a field optional OR have a minimum string contraint?

I have a field where I want the value to either be optional OR have the field have a minimum length of 4 .

I've tried the following:

export const SocialsSchema = z.object({
  myField: z.optional(z.string().min(4, "Please enter a valid value")),
});

This passes if I used a value like: "good" , but if I've got an empty value then it fails.

How do I correctly implement a constraint using zod schemas to make an optional value with a minimum constraint if the value is not empty?

Is it possible to do this without using regex or a regex solution the only way?

In your case, you consider "" to be the same as undefined (ie: when the string is empty, it's like there's no string at all).

It's implementable in Zod this way:

import { z } from "zod";
import { strict as assert } from "node:assert";

// `myString` is a string that can be either optional (undefined or missing),
// empty, or min 4
const myString = z
  .union([z.string().length(0), z.string().min(4)])
  .optional()
  .transform(e => e === "" ? undefined : e);

const schema = z.object({ test: myString });

assert( schema.parse({}).test === undefined ); // missing string
assert( schema.parse({ test: undefined }).test === undefined ); // string is undefined
assert( schema.parse({ test: "" }).test === undefined ); // string is empty
assert( schema.parse({ test: "1234" }).test === "1234" ); // string is min 4

// these successfully fail
assert( schema.safeParse({ test: "123" }).success !== true );
assert( schema.safeParse({ test: 3.14 }).success !== true );

Here you are:

import { z } from "zod";

export const SocialsSchema = z.object({
  myField: z.string().min(4, "Please enter a valid value").optional()
});
// ok
console.log(SocialsSchema.parse({ myField: undefined }));

// ok
console.log(SocialsSchema.parse({ myField: "1234" }));

// ok
console.log(SocialsSchema.parse({ myField: "" }));

// throws min error
console.log(SocialsSchema.parse({ myField: "123" }));

Based on this Github issue and it's answer

Use the or -option in-combined with optional & literal, like this.

export const SocialsSchema = z.object({
  myField: z.string().min(4, "Please enter a valid value"))
        .optional()
        .or(z.literal('')),
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM