fix: update les 4

This commit is contained in:
2026-03-03 13:33:10 +01:00
parent e8170ec2b4
commit d79449ea52
3 changed files with 198 additions and 363 deletions

View File

@@ -977,31 +977,28 @@ _[Pauzeer. Maak oogcontact.]_
"Huiswerk voor volgende week:" "Huiswerk voor volgende week:"
_[Schrijf op en stuur ook via email/Canvas:]_ _[Schrijf op en stuur ook via email/Teams:]_
"**Huiswerk Les 4:** "**Huiswerk Les 4:**
1. **Finish all 8 TypeScript Escaperoom rooms** (if not done today) 1. **Download `les4-huiswerk-js-converter.zip`** van Teams
2. **Download de JS→TS Converter zip** van Canvas 2. Je krijgt 4 JavaScript bestanden: users, products, orders, utils
- Convert 3-5 JavaScript files to TypeScript 3. Zet ze allemaal om naar TypeScript — interfaces schrijven, union types, functies typen
- Voeg types toe aan alle functies en variabelen 4. De tests staan al in TypeScript — die zijn je hints!
- Zorg dat TypeScript compiler 0 errors geeft 5. `npm run check` moet 0 errors geven, `npm test` moet groen zijn
3. **Prepare for Les 5** — TypeScript + React 6. **Geen `any`!** Als ik `any` zie, stuur ik het terug.
- Denk: hoe zouden je React props getypeerd worden?
Room 1-8 van de escaperoom moet af. Als je niet klaar bent vandaag, je hebt de week om het af te maken. Volgende week bouw je hierop voort." En als je de escaperoom nog niet af hebt: maak die ook af."
_[Toon Slide 22 preview.]_ _[Toon Slide 22 preview.]_
"**Volgende week: Les 5. TypeScript + React.**" "**Volgende week: Les 5. TypeScript voor React.**"
"Jullie weten nu: types voorkomen fouten. Functies typen. Interfaces. Volgende week: React components. Props zijn... functies. Dus: props typen. useState? Het returned state EN een setter — beide getypd. Events? Handlers getypd." "Jullie weten nu de basis: types, interfaces, union types, functies typen. Volgende week pakken we het volgende level: hoe gebruik je TypeScript in React? Props typen, useState met types, event handlers, API calls. Dat is de laatste stap voordat we in Les 6 met Next.js beginnen."
"**TypeScript + React = superkracht.** Cursor snapt je code beter. Minder bugs. Betere autocomplete."
_[Maak oogcontact, glimlach.]_ _[Maak oogcontact, glimlach.]_
"Jullie hebben vandaag veel geleerd. TypeScript lijkt misschien veel regels. Maar denk eraan: elke rode squiggle is TypeScript die zegt: 'Hé, ik help je.' Niet iets wat boos is. Het is helpful." "Jullie hebben vandaag veel geleerd. TypeScript lijkt misschien veel regels. Maar denk eraan: elke rode squiggle is TypeScript die zegt: 'Hé, ik help je.' Het is niet boos — het is helpful."
"Goed gedaan vandaag. Tot volgende keer!" "Goed gedaan vandaag. Tot volgende keer!"

View File

@@ -709,31 +709,28 @@ En oefening. Je bent nooit klaar met TypeScript. Er is altijd meer om te leren.
### Op de Slide ### Op de Slide
**Huiswerk (les 4):** **Huiswerk (les 4):**
- Finaliseer zoveel escaperoom kamers als je kan - Download `les4-huiswerk-js-converter.zip` van Teams
- Verzend je TypeScript file naar me (geen `any`!) - Zet 4 JavaScript bestanden om naar TypeScript
- Lees het TypeScript Handbook intro (5 minuten) - Schrijf interfaces, union types, typed functies
- `npm run check` = 0 errors, `npm test` = groen
- Geen `any` toegestaan!
**Preview les 5 - Next.js Basics:** **Preview les 5 - TypeScript voor React:**
- Next.js setup - Generics & utility types
- File-based routing - Props & state typen in React
- Eerste pagina's maken - Event handlers & async functies typen
- TypeScript in Next.js - API responses typen met `Promise<T>`
- Deploy naar Vercel
Visual: Next.js logo met pijl naar "Les 5" Visual: TypeScript logo → React logo → "Les 5"
### Docentnotities ### Docentnotities
"Huiswerk: finaliseer die escaperoom. Verzend je file naar me. Ik wil geen `any` zien, anders stuur ik het terug! "Huiswerk: jullie krijgen een JavaScript project met 4 bestanden — users, products, orders, utils. Alles moet omgezet worden naar TypeScript. Interfaces schrijven, union types gebruiken, functies typen. De tests staan al in TypeScript, die vertellen je wat de verwachte types zijn. `npm run check` moet 0 errors geven en `npm test` moet groen zijn. Geen `any`!
En lees het TypeScript Handbook intro. Niet heel veel tijd, maar het helpt je context. Volgende les gaan we verder met TypeScript, maar dan voor React. Hoe type je props? Hoe werkt useState met types? Hoe type je een API call? Dat is de brug naar Les 6, waar we beginnen met Next.js.
Volgende les? NEXT.JS. Dit is waar het echt spannend wordt. Jullie gaan echte web apps bouwen met React, TypeScript, en all the bells and whistles. Dus zorg dat je huiswerk doet — je hebt die basis nodig.
Next.js is het framework dat everyone uses. Vercel (de makers) gebruiken het. Jullie gaan het morgen gebruiken. Goed werk vandaag! Tot volgende keer!"
Dus zorg dat je huiswerk doet. Het volgende is big.
Goed werk vandaag! Ik ben trots op jullie. Tot volgende keer!"
--- ---

View File

@@ -1,393 +1,234 @@
# Les 5: TypeScript Basics # Les 5: TypeScript voor React
--- ---
## Hoofdstuk ## Hoofdstuk
**Deel 2: Technical Foundations** (Les 5-9) **Deel 2: Technical Foundations** (Les 4-9)
## Beschrijving ## Beschrijving
Introductie tot TypeScript voor React developers. Leer waarom TypeScript waardevol is, hoe je types schrijft, en hoe je het combineert met React. 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 ## Te Behandelen
### Waarom TypeScript? ### Generics (20 min)
- Waarom generics? Herbruikbare, type-safe code
**Het probleem met JavaScript:** - `Array<T>`, `Promise<T>` — generics die ze al kennen
```javascript - Eigen generics schrijven: `function getFirst<T>(items: T[]): T`
function greet(name) { - Generics met constraints: `<T extends { id: string }>`
return "Hello, " + name.toUpperCase(); - `keyof` operator: `function getValue<T, K extends keyof T>(obj: T, key: K): T[K]`
}
greet(42); // Runtime error! 42.toUpperCase is not a function
```
**De oplossing met TypeScript:**
```typescript
function greet(name: string): string {
return "Hello, " + name.toUpperCase();
}
greet(42); // Compile error! Argument of type 'number' is not assignable to type 'string'
```
**Voordelen:**
- Fouten vinden VOORDAT je code runt
- Betere autocomplete in je editor
- Code is zelf-documenterend
- AI tools begrijpen je code beter
---
### Basic Types
```typescript ```typescript
// Primitives // Generic functie
let name: string = "Tim"; function wrapInArray<T>(value: T): T[] {
let age: number = 25; return [value];
let isStudent: boolean = true; }
// Arrays wrapInArray("hello"); // string[]
let numbers: number[] = [1, 2, 3]; wrapInArray(42); // number[]
let names: string[] = ["Tim", "Anna"];
// Alternative array syntax // Met constraint
let scores: Array<number> = [90, 85, 88]; function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {
return obj[key];
// Objects }
let user: { name: string; age: number } = {
name: "Tim",
age: 25
};
``` ```
--- ---
### Type Inference ### Utility Types (15 min)
- `Partial<T>` — alle properties optioneel (handig voor updates)
TypeScript raadt types vaak zelf: - `Pick<T, K>` — selecteer specifieke properties
- `Omit<T, K>` — alles behalve specifieke properties
```typescript - `Record<K, V>` — key-value mapping
// TypeScript weet dat dit een string is - Praktisch voorbeeld: `updateUser(id: string, data: Partial<User>)`
let message = "Hello"; // type: string
// TypeScript weet dat dit een number is
let count = 42; // type: number
// TypeScript weet wat de functie returned
function double(x: number) {
return x * 2; // return type: number (inferred)
}
```
**Regel:** Je hoeft niet altijd types te schrijven. Laat TypeScript inferren waar mogelijk.
---
### Interfaces
Voor het beschrijven van object shapes:
```typescript ```typescript
interface User { interface User {
id: number; id: string;
name: string; name: string;
email: string; email: string;
isActive: boolean; age: number;
} }
const user: User = { // Partial: voor update functies
id: 1, function updateUser(id: string, updates: Partial<User>): User { ... }
name: "Tim", updateUser("1", { name: "Tim" }); // alleen name updaten
email: "tim@example.com",
isActive: true
};
// Optional properties met ? // Omit: voor create functies (id wordt server-side gegenereerd)
interface Product { type CreateUserInput = Omit<User, "id">;
id: number;
name: string; // Pick: voor specifieke views
price: number; type UserPreview = Pick<User, "id" | "name">;
description?: string; // optioneel
}
``` ```
--- ---
### Type Aliases ### React Props Typen (20 min)
- Interface voor component props
Alternatief voor interfaces, meer flexibel: - Children typen met `React.ReactNode`
- Callback props: `onClick: () => void`, `onChange: (value: string) => void`
- Spread props en prop forwarding
- Default values met destructuring
```typescript ```typescript
// Type alias voor object interface CardProps {
type User = { title: string;
id: number; children: React.ReactNode;
name: string; variant?: "default" | "highlighted";
}; onClose?: () => void;
// Type alias voor union types
type Status = "pending" | "approved" | "rejected";
// Type alias voor functie
type GreetFunction = (name: string) => string;
```
**Interface vs Type:**
- Interface: voor objecten, kan extended worden
- Type: voor alles, meer flexibel
---
### TypeScript met React
**Props typen:**
```typescript
// Interface voor props
interface ButtonProps {
label: string;
onClick: () => void;
disabled?: boolean;
} }
// Component met typed props function Card({ title, children, variant = "default", onClose }: CardProps) {
function Button({ label, onClick, disabled = false }: ButtonProps) {
return ( return (
<button onClick={onClick} disabled={disabled}> <div className={`card card-${variant}`}>
{label} <h2>{title}</h2>
</button> {onClose && <button onClick={onClose}>×</button>}
); {children}
}
// Gebruik
<Button label="Click me" onClick={() => console.log("Clicked!")} />
```
---
### useState met Types
```typescript
import { useState } from 'react';
// Type inference werkt vaak
const [count, setCount] = useState(0); // number
// Explicit type voor complexe data
interface User {
id: number;
name: string;
}
const [user, setUser] = useState<User | null>(null);
// Array van objecten
const [users, setUsers] = useState<User[]>([]);
```
---
### Generics Basics
Generics maken code herbruikbaar:
```typescript
// Array is een generic type
const numbers: Array<number> = [1, 2, 3];
const names: Array<string> = ["Tim", "Anna"];
// Promise is een generic type
async function fetchUser(): Promise<User> {
const response = await fetch('/api/user');
return response.json();
}
// Je kunt ook eigen generics maken
function firstElement<T>(arr: T[]): T | undefined {
return arr[0];
}
const first = firstElement([1, 2, 3]); // type: number | undefined
```
---
### Veelvoorkomende Errors
**Error 1: Type 'X' is not assignable to type 'Y'**
```typescript
let name: string = 42; // Error!
// Fix: gebruik correct type
let name: string = "Tim";
```
**Error 2: Property 'X' does not exist on type 'Y'**
```typescript
interface User { name: string; }
const user: User = { name: "Tim" };
console.log(user.age); // Error! 'age' bestaat niet
// Fix: voeg property toe aan interface
```
**Error 3: Object is possibly 'undefined'**
```typescript
const users: User[] = [];
console.log(users[0].name); // Error! users[0] kan undefined zijn
// Fix: check eerst
if (users[0]) {
console.log(users[0].name);
}
```
---
### JS naar TS Omzetten
**Stap 1:** Rename `.js` naar `.tsx` (voor React) of `.ts`
**Stap 2:** Fix de rode errors - meestal:
- Voeg types toe aan function parameters
- Maak interfaces voor objecten
- Handle nullable values
**Voorbeeld:**
```javascript
// Voorheen (JavaScript)
function UserCard({ user }) {
return <div>{user.name}</div>;
}
```
```typescript
// Nu (TypeScript)
interface User {
id: number;
name: string;
}
interface UserCardProps {
user: User;
}
function UserCard({ user }: UserCardProps) {
return <div>{user.name}</div>;
}
```
---
## Tools
- OpenCode/WebStorm
- TypeScript (via Next.js)
- React
---
## Lesopdracht (2 uur)
### TypeScript Hands-on
**Deel 1: JS naar TS Omzetten (45 min)**
Gegeven JavaScript component:
```javascript
function ProductCard({ product, onAddToCart }) {
return (
<div className="p-4 border rounded">
<h2>{product.name}</h2>
<p>${product.price}</p>
{product.description && <p>{product.description}</p>}
<button onClick={() => onAddToCart(product.id)}>
Add to Cart
</button>
</div> </div>
); );
} }
``` ```
Zet dit om naar TypeScript: ---
1. Maak `Product` interface
2. Maak `ProductCardProps` interface
3. Type de component
4. Fix alle TypeScript errors
**Deel 2: Interfaces Schrijven (30 min)** ### 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
Maak interfaces voor: ```typescript
const [user, setUser] = useState<User | null>(null);
const [products, setProducts] = useState<Product[]>([]);
const [loading, setLoading] = useState(false); // inference: boolean
1. **User** met: id, name, email, avatar (optioneel), createdAt useEffect(() => {
2. **Product** met: id, name, price, description (optioneel), inStock, category async function fetchData() {
3. **Order** met: id, userId, products (array), total, status (pending/shipped/delivered) setLoading(true);
const response = await fetch("/api/users");
const data: User[] = await response.json();
setUsers(data);
setLoading(false);
}
fetchData();
}, []);
```
**Deel 3: React Component met Types (45 min)** ---
Bouw een `UserList` component: ### Event Handlers Typen (10 min)
- Props: users array, onSelectUser callback - `React.ChangeEvent<HTMLInputElement>`
- State: selectedUserId (number of null) - `React.FormEvent<HTMLFormElement>`
- Toon lijst van users, highlight geselecteerde - `React.MouseEvent<HTMLButtonElement>`
- Tip: hover in Cursor om het juiste event type te vinden
Alle types moeten correct zijn. Geen `any` gebruiken! ```typescript
function SearchForm() {
const [query, setQuery] = useState("");
### Deliverable const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
- ProductCard.tsx met correcte types setQuery(e.target.value);
- types.ts met alle interfaces };
- UserList.tsx volledig getypt
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) ## Huiswerk (2 uur)
### TypeScript Verdieping ### Extend het Dashboard
**Deel 1: Drie Components Bouwen (1 uur)** Bouw voort op de lesopdracht:
Bouw volledig in TypeScript: 1. **Shopping Cart** toevoegen met getypte state (`CartItem[]`)
2. **API simulatie** — maak een `fetchProducts()` functie met `Promise<Product[]>`
1. **SearchInput** component 3. **Utility types gebruiken**`Partial<Product>` voor updates, `Omit<Product, "id">` voor create
- Props: value, onChange, placeholder (optioneel) 4. **Bonus: Generic `DataTable<T>` component** — werkt met elke array van objecten
- Volledig getypt
2. **DataTable** component
- Generic: werkt met elk type data
- Props: data array, columns config
- Type-safe rendering
3. **Modal** component
- Props: isOpen, onClose, title, children
- Correct gebruik van React.ReactNode
**Deel 2: Eindproject Interfaces (30 min)**
Bedenk de data structuur voor je eindproject:
- Welke entiteiten heb je? (users, posts, products, etc.)
- Maak interface voor elke entiteit
- Documenteer relaties tussen entiteiten
**Deel 3: Cheat Sheet (30 min)**
Maak persoonlijke TypeScript cheat sheet:
- Meest gebruikte types
- Interface vs Type wanneer
- Common patterns met React
- Hoe je errors oplost
### Deliverable ### Deliverable
- 3 TypeScript components - Werkend React project met TypeScript
- types/index.ts met eindproject interfaces - Alle components volledig getypt
- TypeScript cheat sheet (1 pagina) - `npm run check` = 0 errors
--- ---
## Leerdoelen ## Leerdoelen
Na deze les kan de student: Na deze les kan de student:
- Uitleggen waarom TypeScript waardevol is - Generics schrijven en toepassen
- Basic types gebruiken (string, number, boolean, arrays) - Utility types gebruiken (Partial, Pick, Omit, Record)
- Interfaces en type aliases schrijven - React component props correct typen
- React components typen met props - useState en useEffect met types gebruiken
- useState met types gebruiken - Event handlers typen (ChangeEvent, FormEvent, MouseEvent)
- Generics op basisniveau begrijpen - Async functies en API responses typen met Promise<T>
- JavaScript code omzetten naar TypeScript - Een custom hook schrijven met correcte return types
- TypeScript errors lezen en oplossen