Что такое Зод?

Zod — это библиотека проверки схемы, основанная на TypeScript, со статическим выводом типов. Он строится со следующими целями:

  • Сначала TypeScript. Zod построен на TypeScript для TypeScript. Это означает, что вам не нужно изучать новый синтаксис для описания ваших данных. Схемы Zod — это просто типы TypeScript.
  • Вывод типа. Зод пытается сделать как можно больше выводов, поэтому вам не нужно все записывать. Например, если вы передадите строку z.number(), Зод сделает вывод, что вам нужна схема, которая проверяет числа, а не строки.
  • Крошечный размер пакета. Зод крошечный. Он не имеет зависимостей и имеет размер менее 4 КБ в минифицированном и сжатом виде.
  • Поддержка браузера и Node.js. Zod работает как в Node.js, так и в браузере.
  • Отличные сообщения об ошибках. Zod имеет отличные сообщения об ошибках из коробки. Он также имеет мощный API ошибок, который позволяет вам настраивать сообщения об ошибках по своему вкусу.

Монтаж

npm install zod

Зод Утилиты

Zod имеет ряд служебных функций, которые можно использовать для создания схем:

zod.string()

Создает схему, которая проверяет строки.

Пример

const name = z.string();
const data = name.safeParse("John"); // Success ✅
const data = name.safeParse(42); // Error ❌zod.number()

Создает схему, которая проверяет числа.

Пример

const age = z.number();
const data = age.safeParse(42); // Success ✅
const data = age.safeParse("John"); // Error ❌

zod.boolean()

Создает схему, которая проверяет логические значения.

Пример

const isHappy = z.boolean();
const data = isHappy.safeParse(true); // Success ✅
const data = isHappy.safeParse("John"); // Error ❌

zod.array()

Создает схему, которая проверяет массивы.

Пример

const names = z.array(z.string());
const data = names.safeParse(["John", "Jane"]); // Success ✅
const data = names.safeParse([42]); // Error ❌

zod.undefined()

Создает схему, которая проверяет undefined.

Пример

const itsHappy = z.undefined();
const data = isHappy.safeParse(undefined); // Success ✅
const data = isHappy.safeParse("John"); // Error ❌

zod.preprocess()

Создает схему, которая предварительно обрабатывает данные перед их проверкой. Иногда вам нужно предварительно обработать данные перед их проверкой. Например, вы можете захотеть обрезать пробелы в строке перед ее проверкой. Вы можете сделать это с помощью zod.preprocess(). Или вы используете zod для проверки тела запроса API, вы можете использовать его для логических или числовых значений. Например, вы можете захотеть преобразовать строку «true» в логическое значение «истина» перед ее проверкой.

Пример

Удаление пробелов из строки:

const name = z.string().preprocess((val) => val.trim());
const data = name.safeParse("John "); // Success ✅
const data = name.safeParse("John"); // Success ✅
const data = name.safeParse(42); // Error ❌

Преобразование строки в логическое значение:

const isHappy = z.boolean().preprocess(Boolean, z.boolean());
const data = isHappy.safeParse("true"); // Success ✅
const data = isHappy.safeParse("false"); // Success ✅
const data = isHappy.safeParse("John"); // Error ❌

Преобразовать строку в число:

const age = z.number().preprocess(Number, z.number());
const data = age.safeParse("42"); // Success ✅
const data = age.safeParse("John"); // Error ❌

Преобразование массива строк в массив чисел:

const ages = z.array(z.string())
            .preprocess(
                (val) => val.map(Number),
            z.array(z.number()));
const data = ages.safeParse(["42", "43"]); // Success ✅
const data = ages.safeParse(["John"]); // Error ❌

zod.optional()

Создает схему, которая делает значение необязательным. Это означает, что значение может быть либо типом схемы, либо undefined.

Пример

const person = z.object({
    name: z.string().optional(),
});

const data = person.safeParse({
    name: "John",
}); // Success ✅
const data = person.safeParse({}); // Success ✅

zod.object()

Создает схему, которая проверяет объекты.

Пример

const person = z.object({
    name: z.string(),
    age: z.number(),
});

const data = person.safeParse({
    name: "John",
    age: 42,
}); // Success ✅
const data = person.safeParse({
    name: "John",
    age: "42",
}); // Error ❌

zod.union()

Создает схему, которая проверяет объединение нескольких схем.

Пример

const name = z.union([z.string(), z.number()]);

const data = name.safeParse("John"); // Success ✅
const data = name.safeParse(42); // Success ✅

Определение типа схемы

Схемы Zod — это просто типы TypeScript. Это означает, что вы можете использовать их для определения типа переменной. Например, если у вас есть схема, которая проверяет строку, вы можете использовать ее для определения типа переменной:

const name = z.string();

type Name = z.infer<typeof name>;
const data: Name = "John"; // Success ✅
const data: Name = 42; // Error ❌

Методы схемы Зод

Схемы Zod имеют ряд методов, которые можно использовать для проверки данных:

safeParse()

Проверяет данные и возвращает объект ZodSafeParseOutput. Это рекомендуемый способ проверки данных.

Пример

const name = z.string();
const data = name.safeParse("John"); // Success ✅
const data = name.safeParse(42); // Error ❌

parse()

Проверяет данные и возвращает проанализированные данные. Если данные неверны, выдает ошибку. Рекомендуется использовать safeParse() вместо parse().

Пример

const name = z.string();
const data = name.parse("John"); // Success ✅
const data = name.parse(42); // Error ❌

.merge()

Объединяет две схемы вместе.

Пример

const person = z.object({
    id: z.string(),
    name: z.string(),
});

const age = z.object({
    age: z.number(),
});
const personWithAge = person.merge(age); 
type PersonWithAge = z.infer<typeof personWithAge>; // {id: string, name: string, age: number}
const data = personWithAge.safeParse({
    id: "1",
    name: "John",
    age: 42,
}); // Success ✅
const data = personWithAge.safeParse({
    id: "1",
    name: "John",
    age: "42",
}); // Error ❌

pick()

pick() можно использовать для выбора свойств объекта.

Пример

const person = z.object({
    id: z.string(),
    name: z.string(),
});

const personWithName = person.pick({name: true});
type PersonWithName = z.infer<typeof personWithName>; // {name: string}
const data = personWithName.safeParse({
    name: "John",
}); // Success ✅
const data = personWithName.safeParse({
    id: "1",
    name: "John",
}); // Error ❌

omit()

omit() можно использовать для исключения свойств объекта.

Пример

const person = z.object({
    id: z.string(),
    name: z.string(),
});

const personWithoutName = person.omit({name: true});
type PersonWithoutName = z.infer<typeof personWithoutName>; // {id: string}
const data = personWithoutName.safeParse({
    id: "1",
}); // Success ✅
const data = personWithoutName.safeParse({
    id: "1",
    name: "John",
}); // Error ❌

partial()

partial() делает все свойства необязательными.

Пример

const person = z.object({
    id: z.string(),
    name: z.string(),
});

const partialPerson = person.partial();
type PartialPerson = z.infer<typeof partialPerson>; // {id?: string, name?: string}
const data = partialPerson.safeParse({
    id: "1",
}); // Success ✅
const data = partialPerson.safeParse({
    name: "John",
}); // Success ✅
const data = partialPerson.safeParse({
    id: "1",
    name: "John",
}); // Success ✅

deepPartial()

Подобно partial(), но рекурсивно делает все свойства необязательными.

Пример

const person = z.object({
    id: z.string(),
    name: z.string(),
    address: z.object({
        street: z.string(),
        city: z.string(),
    }),
});

const partialPerson = person.deepPartial();
type PartialPerson = z.infer<typeof partialPerson>; // {id?: string, name?: string, address?: {street?: string, city?: string}}
const data = partialPerson.safeParse({
    id: "1",
}); // Success ✅
const data = partialPerson.safeParse({
    name: "John",
}); // Success ✅
const data = partialPerson.safeParse({
    id: "1",
    address: {
        street: "Main Street",
    },
}); // Success ✅

required()

В отличие от partial(), required() делает все необходимые свойства.

Пример

const person = z.object({
    id: z.string().optional(),
    name: z.string().optional(),
});

type Person = z.infer<typeof person>; // {id?: string, name?: string}
const requiredPerson = person.required();
type RequiredPerson = z.infer<typeof requiredPerson>; // {id: string, name: string}

const data = requiredPerson.safeParse({
    id: "1",
}); // Error ❌
const data = requiredPerson.safeParse({
    name: "John",
}); // Error ❌
const data = requiredPerson.safeParse({
    id: "1",
    name: "John",
}); // Success ✅

extend()

extend() можно использовать для расширения объекта дополнительными свойствами.

Пример

const person = z.object({
    id: z.string(),
    name: z.string(),
});

const personWithAge = person.extend({
    age: z.number(),
});
type PersonWithAge = z.infer<typeof personWithAge>; // {id: string, name: string, age: number}
const data = personWithAge.safeParse({
    id: "1",
    name: "John",
    age: 42,
}); // Success ✅

refine()

Создает схему, уточняющую данные. Это означает, что он проверяет данные, а затем запускает на них функцию. Если функция возвращает true, данные действительны. Если функция возвращает false, данные недействительны.

Пример

const person = z.object({
    name: z.string(),
});

const personWithName = person.refine((val) => val.name === "John");
const data = personWithName.safeParse({
    name: "John",
}); // Success ✅
const data = personWithName.safeParse({
    name: "Jane",
}); // Error ❌

keyOf()

Создает схему, которая проверяет ключ объекта.

Пример

const person = z.object({
    name: z.string(),
});

const personWithName = person.keyOf();
type PersonWithName = z.infer<typeof personWithName>; // "name"
const data = personWithName.safeParse("name"); // Success ✅
const data = personWithName.safeParse("age"); // Error ❌

Заключение

Как видите, Zod — это мощная библиотека проверки схемы, которая проста в использовании и содержит отличные сообщения об ошибках. Это также очень быстро и имеет крошечный размер пакета. Это отличная альтернатива Joi и Yup.

Для получения дополнительной информации см. Документацию Zod