Formularze bezpieczne typowo i kontrakty odpowiedzi API
Używanie Zod do wyprowadzania typów TypeScript ze schematów oraz walidowania danych formularzy i odpowiedzi API.
Formularze bezpieczne typowo i kontrakty odpowiedzi API to bezpłatna lekcja React Academy na CoddyKit. To lekcja 4 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej React Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs React Academy zawiera 4 lekcji w sumie.
Dlaczego typowane struktury danych mają znaczenie
Formularze i odpowiedzi API to granice, na których dane trafiają do aplikacji z niezaufanych źródeł. Zod pozwala definiować schematy, które zarówno sprawdzają dane w czasie wykonywania, jak i pozwalają wywnioskować typy TypeScriptu.
Podstawy schematów Zod
Definiuj schematy za pomocą płynnego API biblioteki Zod. Użyj z.infer<typeof schema>, aby wyodrębnić typ TypeScriptu.
import { z } from 'zod';
const UserSchema = z.object({
id: z.string().uuid(),
name: z.string().min(1).max(100),
email: z.string().email(),
age: z.number().int().min(0).max(150).optional(),
role: z.enum(['admin', 'user', 'guest']),
});
type User = z.infer<typeof UserSchema>;
// { id: string; name: string; email: string; age?: number; role: 'admin'|'user'|'guest' }React Hook Form z resolverem Zod
Integruj schematy Zod z React Hook Form, aby zapewnić bezpieczną typowo walidację formularzy — TypeScript zna kształt danych formularza i błędów.
import { useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
const LoginSchema = z.object({
email: z.string().email('Invalid email'),
password: z.string().min(8, 'At least 8 characters'),
});
type LoginData = z.infer<typeof LoginSchema>;
function LoginForm() {
const { register, handleSubmit, formState: { errors } } = useForm<LoginData>({
resolver: zodResolver(LoginSchema),
});
const onSubmit = (data: LoginData) => {
// data is LoginData — fully typed, already validated
};
}Walidowanie odpowiedzi API
Parsuj odpowiedzi API za pomocą Zod, aby wykrywać niezgodności struktury na granicy — jeśli API zwróci nieoczekiwane dane, aplikacja otrzyma szczegółowy błąd zamiast awarii w czasie wykonywania głęboko w komponencie.
async function fetchUser(id: string): Promise<User> {
const res = await fetch(`/api/users/${id}`);
const json = await res.json();
return UserSchema.parse(json); // throws ZodError if shape is wrong
}Bezpieczne parsowanie z obsługą błędów
Użyj schema.safeParse(), aby otrzymać obiekt wyniku zamiast wyjątku — to idealne rozwiązanie do walidacji formularzy, gdy należy wyświetlić użytkownikowi błędy.
const result = UserSchema.safeParse(formData);
if (!result.success) {
const errors = result.error.flatten().fieldErrors;
// { name: ['Must be at least 1 character'], email: ['Invalid email'] }
return errors;
}
const user = result.data; // User — fully typedUnie dyskryminowane z Zod
Należy użyć z.discriminatedUnion, aby modelować odpowiedzi API o różnych kształtach zależnie od flagi powodzenia lub błędu.
const ApiResponse = z.discriminatedUnion('ok', [
z.object({ ok: z.literal(true), data: UserSchema }),
z.object({ ok: z.literal(false), error: z.string(), code: z.number() }),
]);
type ApiResult = z.infer<typeof ApiResponse>;
// { ok: true; data: User } | { ok: false; error: string; code: number }Transformacje w Zod
Należy użyć .transform(), aby wymusić określony typ lub zmienić kształt danych podczas parsowania — na przykład przekonwertować ciąg znaków z datą na obiekt Date.
const DateSchema = z.string().transform(s => new Date(s));
// Input: '2024-01-15' → Output: Date object
const EventSchema = z.object({
title: z.string(),
date: z.string().pipe(z.coerce.date()),
});
type Event = z.infer<typeof EventSchema>;
// { title: string; date: Date }Ponowne używanie schematów
Należy wyprowadzać schematy tworzenia i aktualizacji ze schematu bazowego, aby uniknąć duplikowania kodu.
const UserSchema = z.object({ name: z.string(), email: z.string().email() });
// For creation: add password
const CreateUserSchema = UserSchema.extend({ password: z.string().min(8) });
// For update: all fields optional
const UpdateUserSchema = UserSchema.partial();
type CreateUser = z.infer<typeof CreateUserSchema>;
type UpdateUser = z.infer<typeof UpdateUserSchema>;Server Action z Zod
Należy zwalidować dane formularza za pomocą Zod w Server Action Next.js przed odwołaniem do bazy danych.
async function createPost(formData: FormData) {
'use server';
const schema = z.object({ title: z.string().min(3), body: z.string().min(10) });
const result = schema.safeParse(Object.fromEntries(formData));
if (!result.success) return { errors: result.error.flatten().fieldErrors };
await db.post.create({ data: result.data });
revalidatePath('/blog');
redirect('/blog');
}Współdzielone schematy między frontendem a backendem
Należy eksportować schematy Zod ze współdzielonego pakietu, aby frontend i backend korzystały z tej samej logiki walidacji — jeden schemat jako jedyne źródło prawdy.
// packages/schemas/src/user.ts
export const CreateUserSchema = z.object({ ... });
export type CreateUser = z.infer<typeof CreateUserSchema>;
// Frontend imports:
import { CreateUserSchema, CreateUser } from '@company/schemas';
// Backend imports:
import { CreateUserSchema } from '@company/schemas';Komunikaty błędów Zod
Należy dostosować komunikaty błędów dla poszczególnych pól, aby zapewnić lepsze wrażenia użytkownika — resolver automatycznie przekazuje je do wyświetlania błędów formularza.
const RegistrationSchema = z.object({
username: z.string()
.min(3, 'Username must be at least 3 characters')
.max(20, 'Username cannot exceed 20 characters')
.regex(/^[a-z0-9_]+$/, 'Only lowercase letters, numbers, and underscores'),
});Szybki sprawdzian
Co zapewnia z.infer w TypeScript?
Podsumowanie
Należy zdefiniować schematy Zod raz i używać z.infer do wyprowadzania typów TypeScript. W React Hook Form należy używać zodResolver do bezpiecznej typowo walidacji. Odpowiedzi API należy parsować za pomocą Zod na granicy aplikacji, używać safeParse w przypadku błędów prezentowanych użytkownikowi oraz współdzielić schematy między frontendem a backendem za pośrednictwem wspólnego pakietu.
Często zadawane pytania
Czy lekcja „Formularze bezpieczne typowo i kontrakty odpowiedzi API” jest bezpłatna?
Tak — pełny tekst „Formularze bezpieczne typowo i kontrakty odpowiedzi API” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu React Academy, przejdź na CoddyKit PRO. Kurs React Academy zawiera 4 lekcji w sumie.
Co nauczysz się w „Formularze bezpieczne typowo i kontrakty odpowiedzi API”?
Używanie Zod do wyprowadzania typów TypeScript ze schematów oraz walidowania danych formularzy i odpowiedzi API. Ćwiczysz React Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.
Czy potrzebuję doświadczenia, aby zacząć React Academy?
Nie wymagamy żadnego doświadczenia. React Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 4 z 4.
Ile czasu zajmuje lekcja „Formularze bezpieczne typowo i kontrakty odpowiedzi API”?
Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.
Czy mogę pisać i uruchamiać kod w tej lekcji React Academy?
Tak. Każda lekcja React Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.
Wszystkie lekcje w tym kursie
- Rozłączne sumy dla wariantów komponentów
- Typy warunkowe i mapowane w React
- Komponenty polimorficzne z propsem 'as'
- Formularze bezpieczne typowo i kontrakty odpowiedzi API