Form type-safe e contratti delle risposte API
Utilizzi Zod per inferire i tipi TypeScript dagli schemi e validare sia i dati dei form sia le risposte API.
Form type-safe e contratti delle risposte API è una lezione React Academy gratuita su CoddyKit. Questa è la lezione 4 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento React Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso React Academy include 4 lezioni in totale.
Perché sono importanti le strutture dati type-safe
I moduli e le risposte API sono confini attraverso i quali i dati entrano nell'applicazione da fonti non attendibili. Zod consente di definire schemi che eseguono la validazione a runtime e dai quali è possibile inferire i tipi TypeScript.
Basi degli schemi Zod
Definisca gli schemi con l'API fluente di Zod. Utilizzi z.infer<typeof schema> per ricavare il tipo TypeScript.
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 con Zod Resolver
Integri gli schemi Zod con React Hook Form per una validazione dei moduli type-safe: TypeScript conosce la struttura dei dati e degli errori del modulo.
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
};
}Validare le risposte API
Analizzi le risposte API con Zod per rilevare le incompatibilità nella struttura al confine: se l'API restituisce dati imprevisti, riceve un errore dettagliato invece di un arresto anomalo a runtime in profondità nel componente.
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
}Safe Parse per gestire gli errori
Utilizzi schema.safeParse() per ottenere un oggetto risultato invece di generare un'eccezione: è ideale per la validazione dei moduli, quando desidera mostrare gli errori all'utente.
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 typedUnioni discriminate con Zod
Usi z.discriminatedUnion per modellare le risposte API che hanno forme diverse in base a un flag di successo o errore.
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 }Trasformazioni di Zod
Usi .transform() per convertire o rimodellare i dati durante il parsing, ad esempio per convertire una stringa di data in un oggetto 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 }Riutilizzare gli schemi
Derivi gli schemi di creazione e aggiornamento dallo schema di base per evitare duplicazioni.
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 con Zod
Convalidi i dati del modulo in una Server Action di Next.js con Zod prima di accedere al database.
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');
}Schemi condivisi tra frontend e backend
Esporti gli schemi Zod da un pacchetto condiviso, così frontend e backend usano la stessa logica di convalida: uno schema come unica fonte di verità.
// 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';Messaggi di errore di Zod
Personalizzi i messaggi di errore per ogni campo per una UX migliore: Zod li passa automaticamente alla visualizzazione degli errori del modulo tramite il resolver.
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'),
});Verifica rapida
Che cosa fornisce z.infer
Riepilogo
Definisca gli schemi Zod una sola volta e usi z.infer per derivare i tipi TypeScript. Usi zodResolver in React Hook Form per una convalida tipizzata. Analizzi le risposte API con Zod al confine dell'applicazione, usi safeParse per gli errori destinati agli utenti e condivida gli schemi tra frontend e backend tramite un pacchetto condiviso.
Domande Frequenti
La lezione «Form type-safe e contratti delle risposte API» è gratuita?
Sì — il testo completo di «Form type-safe e contratti delle risposte API» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso React Academy, passa a CoddyKit PRO. Il corso React Academy include 4 lezioni in totale.
Cosa imparerò in «Form type-safe e contratti delle risposte API»?
Utilizzi Zod per inferire i tipi TypeScript dagli schemi e validare sia i dati dei form sia le risposte API. Eserciti React Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.
Ho bisogno di esperienza per iniziare React Academy?
Non è richiesta alcuna esperienza precedente. React Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 4 di 4.
Quanto tempo richiede la lezione «Form type-safe e contratti delle risposte API»?
La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.
Posso scrivere ed eseguire codice in questa lezione React Academy?
Sì. Ogni lezione React Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.
Tutte le lezioni di questo corso
- Unioni discriminate per le varianti dei componenti
- Tipi condizionali e mappati in React
- Componenti polimorfici con la prop 'as'
- Form type-safe e contratti delle risposte API