zod: установить min max после преобразования строки в число

У меня есть число или числовая строка, я хочу преобразовать ее в число и продолжить проверку с помощью .min() .max(), но это не работает, как я ожидал

      const numberValid = z.number().or(z.string().regex(/^\d+$/).transform(Number));

const positiveNumber = numberValid.min(0); // method don't exist

3 ответа

По версии3.20, вы можете использоватьz.coerce.number()вот так:

      const numberValid = z.coerce.number().min(0)

numberValid.parse(123) // OK
numberValid.parse(-123) // ERROR
numberValid.parse("123") // OK
numberValid.parse("-123") // ERROR

Проблема в том, что transformсобирается вернуть z.ZodEffectкоторый имеет методы для выполнения дальнейших преобразований, но потерял из виду тот факт, что он был изначально z.string. Метод из z.numberнедоступен, потому что внешний тип будет z.ZodUnionкоторый также не знает об уточнении.

Я думаю, что для того, чтобы получить поведение, которое вы ищете, что-то вроде этого, я бы выбрал такой подход:

      const thing = z
  .number()
  .or(z.string().regex(/\d+/).transform(Number))
  .refine((n) => n >= 0);

Что, по общему признанию, немного не хватает блеска, потому что мы не можем полагаться на minс его упрощенным синтаксисом и более приятными ошибками. Вы можете решить последнюю проблему, добавив { message: 'value was less than 0' }в качестве второго аргумента refine.

       z.string() 
.transform((year) => parseInt(year)) 
.pipe(z.number().min(1900)) 
.transform((year) => year.toString())
Другие вопросы по тегам