Generyki komponentów — wprowadzenie
Budowanie wielokrotnego użytku komponentów z parametrami typów , ograniczeniami i inferencją oraz bezpieczne przekazywanie typowanych render props i kluczy
Generyki komponentów — wprowadzenie to bezpłatna lekcja TypeScript Academy na CoddyKit. To lekcja 3 z 3. 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 TypeScript Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs TypeScript Academy zawiera 3 lekcji w sumie.
Wprowadzenie
Cel: Sprawić, aby jeden komponent działał z wieloma kształtami danych za pomocą <T>. Przekażesz typowany render prop, ograniczysz klucze i pozwolisz TypeScriptowi wywnioskować T na podstawie użycia.
- Generyczne propsy i funkcje renderujące
- Ograniczenia za pomocą
extends - Wyodrębnianie kluczy bez any
Generyczna lista <T>
Generyczna List<T> zapewnia zgodność elementów items i funkcji render. Kod korzystający z komponentu może przekazać dowolne T; inferencja działa, gdy T jest oczywiste.
import React from "react"
type ListProps<T> = { items: T[]; render: (item: T, index: number) => React.ReactNode }
export function List<T>({ items, render }: ListProps<T>) {
return <div style={{ display: "grid", gap: 6 }}>{items.map(render)}</div>
}
export default function App() {
return (
<div style={{ display: "grid", gap: 12 }}>
<List<number> items={[1,2,3]} render={(n) => <span>#{n}</span>} />
<List<{ id: string; name: string }>
items={[{ id: "u1", name: "Ada" }, { id: "u2", name: "Lin" }]}
render={(u) => <strong>{u.name}</strong>}
/>
</div>
)
}Ograniczenia za pomocą extends
Użyj T extends Keyed, aby wymagać pola id dla kluczy. Kod wywołujący otrzyma błąd, jeśli przekaże elementy bez wymaganego pola.
import React from "react"
type Keyed = { id: string }
type KeyListProps<T extends Keyed> = { items: T[]; render: (item: T) => React.ReactNode }
export function KeyList<T extends Keyed>({ items, render }: KeyListProps<T>) {
return (
<ul>
{items.map((x) => (
<li key={x.id}>{render(x)}</li>
))}
</ul>
)
}
export default function App() {
const users = [{ id: "u1", name: "Ada" }, { id: "u2", name: "Lin" }]
return <KeyList items={users} render={(u) => <span>{u.name}</span>} />
}Inferencja T
Parametry typów są zwykle wywnioskowywane z propsów: tutaj T pochodzi z items. Dodawaj adnotację tylko wtedy, gdy inferencja jest niejasna.
import React from "react"
type GridProps<T> = { items: T[]; columns?: number; render: (item: T) => React.ReactNode }
export function Grid<T>({ items, columns = 2, render }: GridProps<T>) {
const css = { display: "grid", gridTemplateColumns: `repeat(${columns}, 1fr)`, gap: 8 }
return <div style={css as React.CSSProperties}>{items.map(render)}</div>
}
export default function App() {
const products = [
{ sku: "p1", title: "Mouse", price: 25 },
{ sku: "p2", title: "Keyboard", price: 80 }
]
// T is inferred from products; no need to annotate
return <Grid items={products} render={(p) => <span>{p.title} — ${p.price}</span>} />
}Pomocnicze funkcje renderujące
Wyodrębniaj wielokrotnego użytku typy Render<T>, aby zwiększyć czytelność. W razie potrzeby dodaj ograniczenie (T extends { id: string }), aby obsługiwać klucze.
import React from "react"
type Render<T> = (item: T) => React.ReactNode
type TableProps<T extends { id: string }> = { items: T[]; renderRow: Render<T> }
export function Table<T extends { id: string }>({ items, renderRow }: TableProps<T>) {
return (
<table>
<tbody>
{items.map((x) => (
<tr key={x.id}><td>{renderRow(x)}</td></tr>
))}
</tbody>
</table>
)
}
export default function App() {
const rows = [ { id: "1", label: "One" }, { id: "2", label: "Two" } ]
return <Table items={rows} renderRow={(r) => <span>{r.label}</span>} />
}Wskazówki i pułapki
Wskazówki:
- Preferuj inferencję; dodawaj adnotacje tylko wtedy, gdy poprawiają czytelność.
- Używaj
extends, aby wyrażać wymagania. - Unikaj
anyw generycznych render propach, ponieważ eliminuje bezpieczeństwo typów.
Sprawdzanie komponentów generycznych
Szybkie sprawdzenie: która deklaracja poprawnie definiuje generyczny komponent React?
Podsumowanie
Podsumowanie: Używaj <T> do tworzenia wielokrotnego użytku komponentów, stosuj extends do ograniczania typów dla kluczy i pozwól inferencji utrzymać zwięzłość kodu.
Często zadawane pytania
Czy lekcja „Generyki komponentów — wprowadzenie” jest bezpłatna?
Tak — pełny tekst „Generyki komponentów — wprowadzenie” 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 TypeScript Academy, przejdź na CoddyKit PRO. Kurs TypeScript Academy zawiera 3 lekcji w sumie.
Co nauczysz się w „Generyki komponentów — wprowadzenie”?
Budowanie wielokrotnego użytku komponentów z parametrami typów , ograniczeniami i inferencją oraz bezpieczne przekazywanie typowanych render props i kluczy Ćwiczysz TypeScript 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ąć TypeScript Academy?
Nie wymagamy żadnego doświadczenia. TypeScript 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 3 z 3.
Ile czasu zajmuje lekcja „Generyki komponentów — wprowadzenie”?
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 TypeScript Academy?
Tak. Każda lekcja TypeScript 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
- Props i children; obsługa zdarzeń; refs
- Stan i reducery; typowanie Context
- Generyki komponentów — wprowadzenie