Files
novi-lessons/Samenvattingen/Les05-Samenvatting.md
2026-03-03 13:33:10 +01:00

235 lines
6.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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<T>`, `Promise<T>` — generics die ze al kennen
- Eigen generics schrijven: `function getFirst<T>(items: T[]): T`
- Generics met constraints: `<T extends { id: string }>`
- `keyof` operator: `function getValue<T, K extends keyof T>(obj: T, key: K): T[K]`
```typescript
// Generic functie
function wrapInArray<T>(value: T): T[] {
return [value];
}
wrapInArray("hello"); // string[]
wrapInArray(42); // number[]
// Met constraint
function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {
return obj[key];
}
```
---
### Utility Types (15 min)
- `Partial<T>` — alle properties optioneel (handig voor updates)
- `Pick<T, K>` — selecteer specifieke properties
- `Omit<T, K>` — alles behalve specifieke properties
- `Record<K, V>` — key-value mapping
- Praktisch voorbeeld: `updateUser(id: string, data: Partial<User>)`
```typescript
interface User {
id: string;
name: string;
email: string;
age: number;
}
// Partial: voor update functies
function updateUser(id: string, updates: Partial<User>): User { ... }
updateUser("1", { name: "Tim" }); // alleen name updaten
// Omit: voor create functies (id wordt server-side gegenereerd)
type CreateUserInput = Omit<User, "id">;
// Pick: voor specifieke views
type UserPreview = Pick<User, "id" | "name">;
```
---
### 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 (
<div className={`card card-${variant}`}>
<h2>{title}</h2>
{onClose && <button onClick={onClose}>×</button>}
{children}
</div>
);
}
```
---
### useState & useEffect Typen (15 min)
- Type inference bij useState: `useState(0)` → number
- Explicit types: `useState<User | null>(null)`
- Arrays: `useState<Product[]>([])`
- useEffect met async patterns
```typescript
const [user, setUser] = useState<User | null>(null);
const [products, setProducts] = useState<Product[]>([]);
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<HTMLInputElement>`
- `React.FormEvent<HTMLFormElement>`
- `React.MouseEvent<HTMLButtonElement>`
- Tip: hover in Cursor om het juiste event type te vinden
```typescript
function SearchForm() {
const [query, setQuery] = useState("");
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setQuery(e.target.value);
};
const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
console.log("Searching:", query);
};
return (
<form onSubmit={handleSubmit}>
<input value={query} onChange={handleChange} />
</form>
);
}
```
---
### API Responses & Async Typen (15 min)
- `Promise<T>` voor async functies
- API response types definiëren
- Error handling met types
- Fetch wrapper met generics
```typescript
interface ApiResponse<T> {
data: T;
status: number;
message: string;
}
async function fetchApi<T>(url: string): Promise<ApiResponse<T>> {
const response = await fetch(url);
if (!response.ok) {
throw new Error(`HTTP error: ${response.status}`);
}
return response.json();
}
// Gebruik
const { data: users } = await fetchApi<User[]>("/api/users");
const { data: product } = await fetchApi<Product>("/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<T>` of `filterBy<T>`)
---
## 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<Product[]>`
3. **Utility types gebruiken**`Partial<Product>` voor updates, `Omit<Product, "id">` voor create
4. **Bonus: Generic `DataTable<T>` 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<T>
- Een custom hook schrijven met correcte return types