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())