Generator schematu Zod
Zamień listę pól „nazwa: typ” albo interface TypeScript na schemat Zod z typem z.infer.
-
1Wprowadź dane
Wpisz treść, wklej tekst lub załaduj plik z dysku. -
2Kliknij przycisk
Narzędzie natychmiast przetworzy Twoje dane w przeglądarce. -
3Pobierz wynik
Skopiuj gotowy tekst lub zapisz plik na urządzeniu.
return "Wynik gotowy w 0.1s";
}
Typy: string, number, int, boolean, date, datetime, email, url, uuid, tablice (string[]), wartości ('a' | 'b'), | null, odwołania do innych schematów (addressSchema). Możesz wkleić też gotowy interface TypeScript.
Schemat Zod (TypeScript)
Pola
Wymagane
Opcjonalne
Linie kodu
Do sprawdzenia
Wszystkie typy rozpoznane
| Pole | Typ wpisany | Zod | Status |
|---|---|---|---|
| id | number | z.number() | OK |
| name | string | z.string() | OK |
| string | z.string() | OK | |
| age? | number | z.number().optional() | OK |
| isActive | boolean | z.boolean() | OK |
Ściąga: typ wpisany i kod Zod
| Wpisujesz | Dostajesz | Znaczenie |
|---|---|---|
| string | z.string() | tekst |
| number, float | z.number() | liczba |
| int, integer | z.number().int() | liczba całkowita |
| boolean, bool | z.boolean() | prawda / fałsz |
| date | z.coerce.date() | zamienia tekst lub liczbę na Date |
| datetime | z.string().datetime() | tekst w formacie ISO 8601 |
| email, url, uuid | z.string().email() / .url() / .uuid() | tekst o danym formacie |
| bigint | z.bigint() | duża liczba całkowita |
| any, unknown | z.any() / z.unknown() | dowolna wartość |
| record, object | z.record(z.string(), z.any()) | obiekt o dowolnych kluczach |
| string[] lub Array<string> | z.array(z.string()) | tablica |
| 'a' | 'b' | z.enum(["a", "b"]) | jedna z wartości |
| string | null | z.string().nullable() | dopuszcza null |
| nazwa?: string | z.string().optional() | pole można pominąć |
| addressSchema | addressSchema | odwołanie do innego schematu (nazwa kończy się na Schema) |
Jak to liczymy
Każda linia „nazwa: typ” staje się polem obiektu. Znak „?” po nazwie dodaje .optional(), „| null” dodaje .nullable(), a oba razem .nullish().
U Ciebie: id: number daje z.number().
object czy strictObject
z.object() domyślnie usuwa nieznane klucze z wyniku parsowania. z.strictObject() zgłasza błąd, gdy w danych pojawi się klucz spoza schematu. Dla danych z zewnątrz (formularze, API) ścisły wariant szybciej wychwytuje literówki.
Typ bez drugiej deklaracji
z.infer<typeof schemat> wyciąga typ TypeScript ze schematu. Zmieniasz schemat w jednym miejscu, a typ aktualizuje się sam.
Typowe pułapki
Typ date daje z.coerce.date(), które zamienia tekst lub liczbę na Date. Jeśli dane mają zostać tekstem ISO, użyj datetime. .optional() pozwala pominąć pole, ale nie przyjmuje null. Nieznany typ zamieniamy na z.string(), więc sprawdź kolumnę Status.
Oceń to narzędzie:
Powiązane narzędzia
Inne narzędzia, które mogą Ci się przydaćGenerator schematu Zod
Generator schematu Zod zamienia listę pól w formacie „nazwa: typ” albo wklejony interface TypeScript na gotowy kod z.strictObject() lub z.object() z typem z.infer. Zod to biblioteka walidacji dla TypeScript działająca w czasie wykonania. Schemat opisuje kształt danych, a z.infer wyciąga z niego statyczny typ — jedno źródło prawdy.
Mapowanie typów
Typ wpisany po dwukropku jest tłumaczony według stałego słownika, bez względu na wielkość liter (Date działa tak samo jak date).
| Wpis | Zod |
|---|---|
| string | z.string(), z opcją „Teksty niepuste”: z.string().min(1) |
| number, float, double | z.number() |
| int, integer | z.number().int() |
| boolean, bool | z.boolean() |
| date | z.coerce.date() |
| datetime | z.string().datetime() |
| z.string().email() | |
| url | z.string().url() |
| uuid | z.string().uuid() |
| bigint | z.bigint() |
| any, unknown | z.any(), z.unknown() |
| object, record | z.record(z.string(), z.any()) |
| Record<string, number> | z.record(z.string(), z.number()) |
| string[] lub Array<string> | z.array(z.string()) |
| 'admin' | 'user' | z.enum(["admin", "user"]) |
| string | number | z.union([z.string(), z.number()]) |
| 'pl', 42, true | z.literal("pl"), z.literal(42), z.literal(true) |
| string | null | z.string().nullable() |
| addressSchema | addressSchema (odwołanie do innego schematu) |
Typ spoza słownika, np. Address albo { street: string }, zamienia się w z.string(), dostaje status „Uwaga” w tabeli pod wynikiem i podbija licznik „Do sprawdzenia”.
Przykład
Dla pól id: number, name: string, email: email i age?: number przy domyślnych opcjach (import, strictObject, typ z.infer) wynik ma 10 linii:
import { z } from "zod";export const userSchema = z.strictObject({ id: z.number(), name: z.string(), email: z.string().email(), age: z.number().optional(),});export type UserSchema = z.infer<typeof userSchema>;
Gdyby e-mail był wpisany jako email: string, dostałbyś samo z.string() bez sprawdzania formatu. Nazwa typu to nazwa schematu z wielką pierwszą literą.
strictObject
Domyślnie z.object() nie zgłasza błędu przy dodatkowych polach, tylko usuwa je z wyniku parse(). strictObject je odrzuca — to bezpieczniejsze przy API, bo wyłapuje literówki i nieoczekiwane dane. W generatorze odpowiada za to opcja „strictObject (odrzucaj nadmiar)”, domyślnie włączona; po jej odznaczeniu dostajesz z.object().
Jak działa generator schematu Zod
Generator czyta tekst linia po linii i każdą linię „nazwa: typ” zamienia na parę klucz-wartość wewnątrz obiektu, gdzie klucz to nazwa pola, a wartość to metoda walidująca, taka jak z.string() albo z.number(). Puste linie, komentarze // i /* */, nagłówek wklejonego interface lub type oraz zamykający nawias są pomijane, podobnie średniki, przecinki i słowo readonly. Linia bez dwukropka i powtórzona nazwa pola trafiają do ostrzeżeń. Limit to 100 pól i 8000 znaków.
Znak „?” po nazwie pola tłumaczony jest na wywołanie .optional() na końcu łańcucha, „| null” w typie na .nullable(), a oba naraz na .nullish(). Zapis „| undefined” działa jak „?”. Różnica jest istotna: pole opcjonalne może w ogóle nie wystąpić, a pole nullable musi zostać przesłane, choć może mieć wartość null. Ograniczeń typu .min(2).max(40) ani wartości domyślnych .default() generator nie dodaje. Jedyny wyjątek to opcja „Teksty niepuste”, która każdy typ string zamienia na z.string().min(1).
Na końcu generator dokłada eksport typu statycznego, dzięki czemu opis walidacji w czasie wykonania i typ widziany przez edytor pochodzą z jednego miejsca. Pod kodem widać liczniki (pola, wymagane, opcjonalne, linie kodu, do sprawdzenia) i tabelę, która pokazuje, jak zamieniono każde pole.
Przykład: schemat formularza rejestracyjnego krok po kroku
- Wpisujemy pola:
id: int,name: string,email: email,age?: int,tags: string[]. Razem 5 pól, z czego 4 są wymagane, a 1 opcjonalne — tyle pokażą liczniki pod wynikiem. - Generator mapuje typy: id na z.number().int(), name na z.string(), email na z.string().email(), age na z.number().int().optional(), tags na z.array(z.string()).
- Zaznaczamy „Teksty niepuste”. Pole name zmienia się w z.string().min(1), a tags w z.array(z.string().min(1)). Email zostaje bez zmian, bo .email() i tak odrzuca pusty tekst.
- Zostawiamy tryb ścisły, bo dane przychodzą z API. Schemat ma 5 dozwolonych kluczy, a cały kod z importem i typem z.infer liczy 11 linii.
- Ograniczenia domenowe dopisujemy ręcznie w skopiowanym kodzie: name na z.string().min(2).max(40), a age na z.number().int().min(18).max(120).
- Test na poprawnych danych: id 42, name „Anna”, email [email protected], age 30, tags [„admin”]. Wszystkie 4 wymagane pola są obecne, opcjonalne age również — walidacja przechodzi i zwraca obiekt w tym samym kształcie.
- Test na danych z nadmiarowym kluczem: ten sam obiekt plus pole role o wartości „admin”. W schemacie jest 5 kluczy, w danych 6, więc parse() rzuca błąd o kodzie unrecognized_keys z nazwą nieznanego pola. Przy z.object() obiekt przeszedłby, a klucz role zniknąłby z wyniku bez ostrzeżenia.
Sytuacja w danych a metoda Zod
| Sytuacja w danych | Metoda w Zod | Efekt walidacji | Jak uzyskać |
|---|---|---|---|
| Pole może w ogóle nie wystąpić | .optional() | Brak klucza jest poprawny, typ dopuszcza undefined | „?” po nazwie |
| Pole może mieć wartość null | .nullable() | Klucz musi wystąpić, ale null przechodzi bez błędu | „| null” w typie |
| Pole może nie wystąpić albo być null | .nullish() | Przechodzi brak klucza, undefined i null | „?” i „| null” razem |
| Pole ma wartość zapasową | .default(...) | Brak klucza przyjmuje wartość domyślną zamiast błędu | dopisz ręcznie |
| Liczba ma być całkowita | .int() | Wartości z częścią ułamkową są odrzucane | typ int |
| Liczba ma mieścić się w zakresie | .min() i .max() | Wartość poza podanym progiem jest odrzucana | dopisz ręcznie |
| Dodatkowe klucze mają być błędem | z.strictObject | Błąd unrecognized_keys z listą nieznanych kluczy | opcja strictObject |
| Zagnieżdżony obiekt w polu | osobny schemat | Walidacja schodzi o poziom niżej i sprawdza pola wewnętrzne | address: addressSchema |
| Tablica obiektów | z.array(itemSchema) | Każdy element tablicy sprawdzany jest osobno | items: itemSchema[] |
Praktyczne wskazówki przy generowaniu schematu
- Trzymaj jeden schemat na kontrakt — jeśli te same dane walidujesz w formularzu i na serwerze, użyj jednego wygenerowanego schematu zamiast dwóch kopii, które z czasem się rozjadą.
- Waliduj na granicy systemu — schemat ma sens tam, gdzie dane wchodzą: żądanie HTTP, odpowiedź API, zawartość formularza. W środku aplikacji operuj już na typach, nie na ponownych sprawdzeniach.
- Nazwy pól zostaw takie jak w źródle. Jeśli API zwraca snake_case, nie zmieniaj nazw w schemacie, bo dopasowanie danych do pól przestanie być oczywiste. Zmianę konwencji rób osobno, po walidacji.
- Zagnieżdżone struktury buduj od dołu: najpierw
addressSchema, potem schemat, który go używa. Odwołanie działa tylko dla nazw kończących się na „Schema”, a schemat musi być zdefiniowany w pliku wcześniej.
Czego narzędzie nie uwzględnia
- Reguł biznesowych — generator odtwarza strukturę typów, ale nie wie, że data końca musi być późniejsza niż data początku, ani że suma pozycji musi zgadzać się z kwotą faktury. Takie warunki dopisujesz samodzielnie, np. przez
.refine(). - Zależności między polami — warunki typu „pole wymagane tylko wtedy, gdy inne ma konkretną wartość” nie wynikają z opisu typów i trzeba je dopisać ręcznie na poziomie całego obiektu.
- Zagnieżdżonych obiektów we wklejonym interface — linia
address: {nie jest rozpoznana, a pola z jej wnętrza trafiają na najwyższy poziom schematu. Wydziel taki obiekt do osobnego interface i wpiszaddress: addressSchema. - Wersji biblioteki — wynik działa w Zod 3 i Zod 4. W Zod 4 zapisy
z.string().email(),.url(),.uuid()i.datetime()są oznaczone jako przestarzałe na rzeczz.email(),z.url(),z.uuid()iz.iso.datetime(), ale nadal działają.
Najczęstsze pytania
Jak oznaczyć pole opcjonalne?
Dopisz „?” do nazwy, np. age?: number. Generator doda .optional(), a przy typie age?: number | null użyje .nullish().
Czy mogę wkleić gotowy interface TypeScript?
Tak. Nagłówek interface User {, zamykający nawias, średniki, komentarze i readonly są pomijane, a każda właściwość staje się polem schematu.
Jak wygenerować schemat Zod dla tablicy obiektów?
Najpierw wygeneruj schemat pojedynczego elementu, np. itemSchema, a potem w schemacie nadrzędnym wpisz items: itemSchema[]. Wynik to z.array(itemSchema), więc walidacja sprawdzi każdy element osobno.
Jak pokazać użytkownikowi błędy walidacji z Zod?
schema.parse(dane) rzuca wyjątek, a schema.safeParse(dane) zwraca obiekt z polem success. Przy błędzie lista error.issues zawiera ścieżkę (path) i komunikat dla każdego pola, więc możesz przypisać komunikaty do konkretnych pól formularza.
Czy można łączyć schematy?
Tak — Zod ma metody extend, pick, omit i partial. Wersję formularza edycji zrobisz np. przez partial().
Czy ten sam schemat Zod mogę użyć na kliencie i na serwerze?
Tak, to jedno z głównych zastosowań biblioteki — ten sam plik ze schematem działa w obu środowiskach. Klient odrzuca dane wcześniej, a serwer i tak sprawdza je ponownie, bo żądanie można wysłać z pominięciem interfejsu.