Componenti generici e utility type
Scriva componenti generici riutilizzabili e utilizzi PropsWithChildren, ComponentProps e Omit.
Componenti generici e utility type è una lezione React Academy gratuita su CoddyKit. Questa è la lezione 3 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é utilizzare componenti generici
I componenti generici si adattano a diversi tipi di dati mantenendo la completa sicurezza dei tipi: una lista, una select o una tabella tipizzata che funziona con qualsiasi struttura di dati.
Una semplice lista generica
Utilizzi un parametro di tipo T sulla funzione per creare un componente lista che esegue il rendering di elementi di qualsiasi tipo.
interface ListProps<T> {
items: T[];
renderItem: (item: T, index: number) => React.ReactNode;
keyExtractor: (item: T) => string;
}
function List<T>({ items, renderItem, keyExtractor }: ListProps<T>) {
return (
<ul>
{items.map((item, i) => (
<li key={keyExtractor(item)}>{renderItem(item, i)}</li>
))}
</ul>
);
}Vincolare i tipi generici
Utilizzi extends per aggiungere vincoli, così TypeScript saprà quali proprietà deve avere il tipo.
interface SelectProps<T extends { id: string; label: string }> {
options: T[];
value: T | null;
onChange: (option: T) => void;
}
function Select<T extends { id: string; label: string }>(
{ options, value, onChange }: SelectProps<T>
) {
return (
<select value={value?.id} onChange={e => onChange(options.find(o => o.id === e.target.value)!)}>
{options.map(o => <option key={o.id} value={o.id}>{o.label}</option>)}
</select>
);
}PropsWithChildren
React.PropsWithChildren<P> aggiunge children?: React.ReactNode a qualsiasi tipo di props: è utile per i componenti wrapper.
function Card({ title, children }: React.PropsWithChildren<{ title: string }>) {
return (
<div className="card">
<h2>{title}</h2>
{children}
</div>
);
}ComponentProps
React.ComponentProps<typeof Component> estrae le props di un componente esistente, utile quando si desidera estenderlo o racchiuderlo in un wrapper.
import { Button } from './Button';
type ExtendedButtonProps = React.ComponentProps<typeof Button> & {
loading?: boolean;
};
function LoadingButton({ loading, children, ...props }: ExtendedButtonProps) {
return (
<Button {...props} disabled={loading || props.disabled}>
{loading ? <Spinner /> : children}
</Button>
);
}ComponentPropsWithoutRef
React.ComponentPropsWithoutRef<'input'> estrae le props dell'elemento HTML senza la prop ref: è ideale per creare wrapper di elementi HTML.
type InputProps = React.ComponentPropsWithoutRef<'input'> & {
label: string;
error?: string;
};
function FormInput({ label, error, ...inputProps }: InputProps) {
return (
<div>
<label>{label}</label>
<input {...inputProps} />
{error && <span className="error">{error}</span>}
</div>
);
}Omit e Pick
Utilizzi Omit<T, Keys> per rimuovere props specifiche e Pick<T, Keys> per mantenere solo props specifiche da un tipo esistente.
interface UserCardProps {
id: string;
name: string;
email: string;
avatar: string;
role: string;
}
// Only expose non-sensitive fields:
type PublicUserCardProps = Omit<UserCardProps, 'email' | 'role'>;
// Or pick exactly what you need:
type AvatarProps = Pick<UserCardProps, 'name' | 'avatar'>;Partial e Required
Partial<T> rende opzionali tutte le props (utile per i moduli di aggiornamento). Required<T> rende obbligatorie tutte le props.
interface UserFormData { name: string; email: string; bio: string; }
// For update: only send changed fields
type UserUpdatePayload = Partial<UserFormData>;
// For create: all fields are mandatory
type UserCreatePayload = Required<UserFormData>;Record per dizionari tipizzati
Record<Keys, Value> crea un tipo oggetto con tipi specifici per le chiavi, utile per le mappe di ricerca e le traduzioni.
type Status = 'idle' | 'loading' | 'success' | 'error';
const statusLabels: Record<Status, string> = {
idle: 'Ready',
loading: 'Loading...',
success: 'Done!',
error: 'Something went wrong',
};ReturnType per i tipi degli hook
Utilizzi ReturnType<typeof useMyHook> per dedurre il tipo restituito da un hook personalizzato senza duplicare manualmente il tipo.
function useCounter(initial: number) {
const [count, setCount] = useState(initial);
return { count, increment: () => setCount(c => c + 1) };
}
type CounterHook = ReturnType<typeof useCounter>;
// { count: number; increment: () => void }Componente tabella generico
Una tabella di dati completamente tipizzata che funziona con qualsiasi struttura delle righe, deduce le chiavi delle colonne e offre comunque il completamento automatico.
interface Column<T> {
key: keyof T;
header: string;
render?: (value: T[keyof T], row: T) => React.ReactNode;
}
function DataTable<T extends object>({ data, columns }: { data: T[]; columns: Column<T>[] }) {
return (
<table>
<thead><tr>{columns.map(c => <th key={String(c.key)}>{c.header}</th>)}</tr></thead>
<tbody>{data.map((row, i) => (
<tr key={i}>{columns.map(c => <td key={String(c.key)}>{c.render ? c.render(row[c.key], row) : String(row[c.key])}</td>)}</tr>
))}</tbody>
</table>
);
}Verifica rapida
Quale tipo utility rimuove chiavi specificate da un'interfaccia TypeScript esistente?
Riepilogo
I componenti generici utilizzano parametri di tipo per mantenere la sicurezza dei tipi con strutture di dati diverse. I tipi utility come Omit, Pick, Partial, ComponentProps e PropsWithChildren eliminano la duplicazione manuale dei tipi e rendono le API dei componenti più componibili.
Domande Frequenti
La lezione «Componenti generici e utility type» è gratuita?
Sì — il testo completo di «Componenti generici e utility type» è 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 «Componenti generici e utility type»?
Scriva componenti generici riutilizzabili e utilizzi PropsWithChildren, ComponentProps e Omit. 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 3 di 4.
Quanto tempo richiede la lezione «Componenti generici e utility type»?
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
- Tipizzazione delle props e dei tipi restituiti dai componenti
- Tipizzazione di eventi e ref in TypeScript
- Componenti generici e utility type
- Tipizzazione del context e dei Custom Hook