# Les 5: TypeScript voor React --- ## Hoofdstuk **Deel 2: Technical Foundations** (Les 4-9) ## Beschrijving Verdieping in TypeScript met focus op React-patronen. Studenten leren generics, utility types, en hoe je React components, hooks, events en API calls correct typt. Voorbereiding op Les 6 waar ze met Next.js aan de slag gaan. **Voorkennis:** Les 4 (TypeScript Fundamentals) — basic types, interfaces, union types, type aliases, functies typen. --- ## Te Behandelen ### Generics (20 min) - Waarom generics? Herbruikbare, type-safe code - `Array`, `Promise` — generics die ze al kennen - Eigen generics schrijven: `function getFirst(items: T[]): T` - Generics met constraints: `` - `keyof` operator: `function getValue(obj: T, key: K): T[K]` ```typescript // Generic functie function wrapInArray(value: T): T[] { return [value]; } wrapInArray("hello"); // string[] wrapInArray(42); // number[] // Met constraint function getProperty(obj: T, key: K): T[K] { return obj[key]; } ``` --- ### Utility Types (15 min) - `Partial` — alle properties optioneel (handig voor updates) - `Pick` — selecteer specifieke properties - `Omit` — alles behalve specifieke properties - `Record` — key-value mapping - Praktisch voorbeeld: `updateUser(id: string, data: Partial)` ```typescript interface User { id: string; name: string; email: string; age: number; } // Partial: voor update functies function updateUser(id: string, updates: Partial): User { ... } updateUser("1", { name: "Tim" }); // alleen name updaten // Omit: voor create functies (id wordt server-side gegenereerd) type CreateUserInput = Omit; // Pick: voor specifieke views type UserPreview = Pick; ``` --- ### React Props Typen (20 min) - Interface voor component props - Children typen met `React.ReactNode` - Callback props: `onClick: () => void`, `onChange: (value: string) => void` - Spread props en prop forwarding - Default values met destructuring ```typescript interface CardProps { title: string; children: React.ReactNode; variant?: "default" | "highlighted"; onClose?: () => void; } function Card({ title, children, variant = "default", onClose }: CardProps) { return (

{title}

{onClose && } {children}
); } ``` --- ### useState & useEffect Typen (15 min) - Type inference bij useState: `useState(0)` → number - Explicit types: `useState(null)` - Arrays: `useState([])` - useEffect met async patterns ```typescript const [user, setUser] = useState(null); const [products, setProducts] = useState([]); const [loading, setLoading] = useState(false); // inference: boolean useEffect(() => { async function fetchData() { setLoading(true); const response = await fetch("/api/users"); const data: User[] = await response.json(); setUsers(data); setLoading(false); } fetchData(); }, []); ``` --- ### Event Handlers Typen (10 min) - `React.ChangeEvent` - `React.FormEvent` - `React.MouseEvent` - Tip: hover in Cursor om het juiste event type te vinden ```typescript function SearchForm() { const [query, setQuery] = useState(""); const handleChange = (e: React.ChangeEvent) => { setQuery(e.target.value); }; const handleSubmit = (e: React.FormEvent) => { e.preventDefault(); console.log("Searching:", query); }; return (
); } ``` --- ### API Responses & Async Typen (15 min) - `Promise` voor async functies - API response types definiëren - Error handling met types - Fetch wrapper met generics ```typescript interface ApiResponse { data: T; status: number; message: string; } async function fetchApi(url: string): Promise> { const response = await fetch(url); if (!response.ok) { throw new Error(`HTTP error: ${response.status}`); } return response.json(); } // Gebruik const { data: users } = await fetchApi("/api/users"); const { data: product } = await fetchApi("/api/products/1"); ``` --- ## Tools - Cursor (Student Plan) - TypeScript - React (via CDN of Vite) --- ## Lesopdracht (75 min) ### Typed React Dashboard Studenten bouwen een kleine React-app met volledig getypte components: **Opdracht:** Bouw een Product Dashboard met: 1. **`ProductCard` component** — props: Product interface, onAddToCart callback 2. **`ProductList` component** — props: Product[], filterCategory (union type) 3. **`SearchBar` component** — props: query string, onChange handler (getypt event) 4. **`useProducts` custom hook** — fetch products, return `{ products, loading, error }` 5. **Alle types in een apart `types.ts` bestand** **Vereisten:** - Geen `any` toegestaan - Alle event handlers correct getypt - useState met expliciete types waar nodig - Minstens 1 generic functie (bijv. een `sortBy` of `filterBy`) --- ## Huiswerk (2 uur) ### Extend het Dashboard Bouw voort op de lesopdracht: 1. **Shopping Cart** toevoegen met getypte state (`CartItem[]`) 2. **API simulatie** — maak een `fetchProducts()` functie met `Promise` 3. **Utility types gebruiken** — `Partial` voor updates, `Omit` voor create 4. **Bonus: Generic `DataTable` component** — werkt met elke array van objecten ### Deliverable - Werkend React project met TypeScript - Alle components volledig getypt - `npm run check` = 0 errors --- ## Leerdoelen Na deze les kan de student: - Generics schrijven en toepassen - Utility types gebruiken (Partial, Pick, Omit, Record) - React component props correct typen - useState en useEffect met types gebruiken - Event handlers typen (ChangeEvent, FormEvent, MouseEvent) - Async functies en API responses typen met Promise - Een custom hook schrijven met correcte return types