# Les 4: TypeScript Fundamentals - Slide Overzicht > Versie 2 - Aangepast voor 65-70 minuten lesmateriaal + 50-60 minuten Escaperoom --- ## Slide 1: Titel - "Les 4: TypeScript Fundamentals" ### Op de Slide - Titel: **Les 4: TypeScript Fundamentals** - Subtitel: "De Kracht van Types" - **Les 4 van 18** (progress indicator) - TypeScript logo - Energetic background, motivational vibe ### Docentnotities Tim opent energiek en vraagt aandacht voor typering. "Hoi iedereen! Welkom bij Les 4. We gaan vandaag echt het fundament leggen voor TypeScript. Wie van jullie heeft al weleens van TypeScript gehoord?" *Pauze voor respons.* "Mooi! TypeScript is één van de meest gebruikte tools in moderne web development. Bedrijven zoals Netflix, Airbnb, Google — ze gebruiken allemaal TypeScript. En vandaag gaan jullie begrijpen waarom." "Vandaag is een dag met veel content maar ook veel hands-on werk. Je zult zelf gaan programmeren, fouten opsporen, en aan het einde van de les een volledige Escaperoom met 10 kamers aanpakken. Dus zet jezelf in orde, zorg dat je goed zit, en laten we gaan!" --- ## Slide 2: Planning Vandaag ### Op de Slide - **Blok 1 (20 min)**: Het Probleem & De Oplossing - Waarom TypeScript? - Het ecosysteem - **Blok 2 (25 min)**: Type Basics - Basic types, arrays, inference, interfaces - **Blok 3 (20 min)**: Geavanceerde Types - Unions, narrowing, guards, intersection, readonly - **PAUZE (15 min)** ☕ - **Blok 4 (50-60 min)**: Hands-On Escaperoom - 10 kamers, progressive difficulty - **Afsluiting (15 min)**: Samenvatting, huiswerk, Les 5 preview **Totaal: ~3 uur** ### Docentnotities Tim gaat door de planning zodat iedereen weet wat te verwachten. "Oké, hier is het plan voor vandaag. We beginnen met het WAAROM van TypeScript — ik wil dat jullie begrijpen wat het probleem is dat TypeScript oplost. Dan gaan we de basics doen: types, arrays, interfaces. Dat klinkt misschien droog, maar ik beloof je dat het interessant is. Daarna duiken we in de coolere stuff: union types, type narrowing, type guards. Dit zijn de concepten waardoor TypeScript echt begint te voelen als superkrachten in je editor. We nemen dan even pauze, en daarna... escaperoom! Tien kamers, elk met een ander TypeScript-probleem dat je moet oplossen. Dit is waar alles bij elkaar komt. Tot slot: samenvatting, huiswerk, en een preview op Les 5 over Generics." --- ## Slide 3: Terugblik Les 3 - Cursor & Debugging ### Op de Slide - **Les 3 samengevat:** - Debugging Tools: breakpoints, step-by-step - Reactive vs Proactive Debugging - Cursor-features: watch expressions, console - **Quote**: "Fouten vinden is 50% van programmeren" ### Docentnotities Tim doet snel terugblik naar vorige les. "Vorige week hebben we geleerd hoe je fouten opzoekt met Cursor. Jullie hebben breakpoints ingesteld, variabelen gewatch, stap voor stap door code gegaan. Dat was reactief debuggen — je wacht tot het kapot gaat en zoekt het dan op. Vandaag gaan we iets beters doen: proactiever. TypeScript helpt je fouten VOORKOMEN voordat je ze debuggen moet. Dat's veel beter. Dus zet die debugging-mindset van vorige week in je achterhoofd — we gaan het vandaag combineren met TypeScript." --- ## Slide 4: Het Probleem met JavaScript ### Op de Slide ```javascript function calculateTotal(price, quantity) { return price * quantity; } const total = calculateTotal("29.99", 5); console.log(total); // "29.9929.9929.9929.9929.99" ❌ ``` - **JavaScript zegt**: "Oké, je vermenigvuldigt een string met een getal?" - **JavaScript doet**: String herhaling in plaats van rekenen! - **Geen error**, code draait gewoon... fout ### Docentnotities Tim laat zien hoe JavaScript stil fouten accepteert. "Ik begin met het probleem. Kijk naar deze functie. Heel eenvoudig: je geeft twee parameters in, het vermenigvuldigt ze. Maar kijk hier: we roepen het aan met een string `'29.99'` en het getal `5`. JavaScript ziet dat en denkt... tja, weet je, ik ga gewoon die string vijf keer herhalen. En GEEN ERROR MELDING. Het werkt gewoon, alleen... niet wat je wil. Dit is het klassieke JavaScript-probleem. De taal is té tolerant. Ze accepteert alles. En dat voelt fijn tot het niet fijn voelt. Stel je voor: dit gebeurt in je webshop. Klanten zien `'29.9929.9929.9929.9929.99'` als prijs. Dat is... slecht. Heel slecht. En je hebt het pas in productie gezien!" --- ## Slide 5: De Oplossing: TypeScript ### Op de Slide ```typescript function calculateTotal(price: number, quantity: number): number { return price * quantity; } const total = calculateTotal("29.99", 5); // ❌ ERROR! // Argument of type 'string' is not assignable to parameter of type 'number'. ``` - **TypeScript zegt**: "Wacht even, je geeft een STRING in maar ik verwacht een NUMBER!" - **Compilatie stopt**, je ziet de fout VOOR je code draait - **Rust** ### Docentnotities Tim laat zien hoe TypeScript hetzelfde probleem voorkomt. "Kijk, nu dezelfde code in TypeScript. We zeggen: `price: number` — dit is een getal. `quantity: number` — ook een getal. En de return-waarde is `number`. Nu, als je het aanroept met een string, geeft TypeScript DIRECT een error. Niet ergens in productie. HIER. In je editor, terwijl je aan het typen bent. En je code draait niet totdat je het hebt opgelost. Je bent GEDWONGEN het goed te doen. Dat is de core van TypeScript: types helpen je fouten voorkomen voordat ze in production terechtkomen." --- ## Slide 6: Waarom TypeScript? - 4 Voordelen ### Op de Slide 1. **Fouten Voorkomen** - Type-fouten, onbekende properties - Minder bugs in productie 2. **Betere Documentatie** - Code zegt waar het voor is - Geen aparte docs nodig 3. **Autocomplete & IntelliSense** - Editor weet wat je kunt doen - Sneller coderen 4. **Veilig Refactoring** - Verander je code, TypeScript waarschuwt je overal **Gebruikers:** Netflix, Airbnb, Google, Microsoft, Facebook ### Docentnotities Tim legt uit waarom het belangrijk is. "Oké, waarom doen alle grote bedrijven dit? Vier redenen. Eén: fouten voorkomen. Als jij een property op een object wil aanroepen die niet bestaat, TypeScript zegt: nope. Niet gebeurd. Dit garandeert dat je code meer betrouwbaar is. Twee: documentatie. Als je ziet `function processOrder(order: Order): Promise`, dan weet je PRECIES wat dit doet. Geen mysteries. De code documenteert zichzelf. Drie: autocomplete. Je typt `order.` en je editor laat alle mogelijke properties zien. Je hoeft niet de documentatie op te zoeken. Je editor weet het. En vier: refactoring. Stel je voor, je hernoemt een property van `username` naar `user_name`. TypeScript zoekt je hele codebase af en zegt: 'je hebt dit op DEZE 47 plekken nog niet aangepast'. Zonder TypeScript zou je dit missen en je app zou kapot zijn. Dat's waarom Netflix, Google, iedereen het gebruikt. Het scheelt gewoon tijd en fouten." --- ## Slide 7: TypeScript in het Ecosysteem ### Op de Slide - **Modern Web Development stacks:** - ✅ Next.js (React + TypeScript) - ✅ React (TypeScript optional maar standaard) - ✅ Vue + TypeScript - ✅ Svelte + TypeScript - ✅ Node.js projects - ✅ Deno (TypeScript built-in) - **Quote**: "TypeScript is de standaard geworden" - **Grafiek**: Groei van TypeScript adoptie over jaren ### Docentnotities Tim laat zien dat TypeScript overal is. "TypeScript is niet meer iets speciaals. Het is de standaard. Kijk naar dit: haast elk modern framework ondersteunt TypeScript out-of-the-box. Next.js? TypeScript. React? TypeScript. Vue? TypeScript. En niet alleen web frameworks. Node.js? Heel veel Node-projecten gebruiken TypeScript. Deno (de 'React van JavaScript runtimes') is eigenlijk GEBOUWD om TypeScript native te runnen. Dit is niet toekomst. Dit is NU. Dus als jij straks een baan zoekt en je kunt TypeScript, je bent aangenomen. Punt." --- ## Slide 8: Basic Types - De Fundamenten ### Op de Slide ```typescript // De drie meest gebruikte types const name: string = "Alice"; const age: number = 25; const isStudent: boolean = true; // Type inference: je hoeft het niet altijd te zeggen const city = "Utrecht"; // TypeScript weet: string const count = 42; // TypeScript weet: number // ❌ DE VIJAND: 'any' let mystery: any = "hello"; mystery = 123; // ✅ Geen error, want 'any' mystery.someMethod(); // ✅ Geen error, TypeScript geeft op // 'any' negeer ALLES wat TypeScript goed aan doet. Avoid it! ``` - **Live coding moment**: Tim typt dit in Cursor en laat errors zien ### Docentnotities Tim geeft energieke uitleg over basics. "Oké, basis types. Drie: string, number, boolean. Je hebt ze waarschijnlijk al eens gezien. string: tekst. number: getallen (zowel heel als decimaal, TypeScript ziet geen verschil). boolean: waar of onwaar. Nu, interessante opmerking: je hoeft TypeScript niet altijd te vertellen wat het type is. Als je `const city = "Utrecht"` schrijft, TypeScript WEET dat het een string is. Dat heet type inference. TypeScript raadt het. Maar soms is het fijn om het expliciet te zeggen, vooral in functies. We komen daar zo op terug. En dan is er 'any'. Let me be clear: `any` is de vijand. Als je `any` gebruikt, zeg je tegen TypeScript: 'Ik geef het op, zeg gewoon ja tegen alles.' En dan heb je de voordelen van TypeScript niet meer. Ik wil dat jullie `any` HATEN. Verdedigen jullie jezelf ertegen." *Tim opent Cursor en typt de voorbeelden in real-time.* --- ## Slide 9: Arrays - Collecties Typen ### Op de Slide ```typescript // Arrays van één type const numbers: number[] = [1, 2, 3]; const colors: Array = ["red", "blue", "green"]; // ❌ Gemengde arrays geven error const mixed: number[] = [1, "two", 3]; // ERROR! // Arrays van objecten (preview) interface Product { id: number; name: string; price: number; } const products: Product[] = [ { id: 1, name: "Laptop", price: 999 }, { id: 2, name: "Mouse", price: 25 } ]; // Lege array: TypeScript gist het type const items = []; // any[] - niet ideaal! const items: string[] = []; // Beter ``` ### Docentnotities Tim legt arrays en collections uit. "Arrays. Je kent ze van JavaScript. Nu, in TypeScript kun je zeggen wat erin zit. `number[]` — een array van getallen. Heel duidelijk. `Array` — hetzelfde maar ander syntaxen. Beide werken, kies wat je mooier vindt. Dus als je probeert een string in een `number[]` te doen, TypeScript blokkeert je. Goed! En kijk hier — arrays van objecten. We gaan later veel meer hierover doen, maar het idee: je definiëert een interface (meer daarover zo), en dan maak je een array van die type. Elk element in die array moet die interface matchen. Let op de lege array: als je `const items = []` doet, TypeScript weet niet wat erin hoort. Het wordt `any[]`. Niet goed. Beter: `const items: string[] = []` — nu weet TypeScript wat je verwacht. Dit soort detail voorkomen bugs. Goed gedaan, TypeScript." --- ## Slide 10: Type Inference - TypeScript Raadt ### Op de Slide ```typescript // Variabelen: TypeScript raadt het type const message = "Hello"; // string const count = 42; // number const isDone = false; // boolean // Functies: je MOET het meestal expliciet zeggen function greet(name) { // ❌ Wat is 'name'? Onbekend console.log("Hallo, " + name); } function greet(name: string) { // ✅ Duidelijk: string console.log("Hallo, " + name); } // Hover in Cursor: zie het type! // Als je over 'message' hovert → "const message: string" ``` - **Live demo**: Tim hovert over variabelen in Cursor, laat types zien ### Docentnotities Tim legt uit wat inference is en wanneer je expliciet moet zijn. "Type inference: TypeScript raadt. Dus als je een getal toewijst, weet het dat het een getal is. Maar functies zijn anders. Als je een parameter hebt zonder type, weet TypeScript niet wat het is. Je MOET het zeggen. Waarom? Omdat de volgende persoon die jouw functie aanroept niet kan weten wat het verwacht. Als je `greet(name)` ziet en geen type staat erop, huh? Is het een string? Getal? Object? Onduidelijk. Dus regel: geef aan parameters en return types. Variabelen kunnen inference gebruiken. En proef dit: in Cursor kun je over bijna alles hoveren en het type zien. Probeer het. Hover over `message` — je ziet `const message: string`. Dit is супер handig voor debuggen." *Tim opent Cursor, hovert over een variabele.* --- ## Slide 11: Interfaces - Object Vormen Definiëren ### Op de Slide ```typescript // Interface: een 'blauwdruk' voor objecten interface User { id: number; name: string; email: string; age: number; } // Dit object matcht de interface const user: User = { id: 1, name: "Alice", email: "alice@example.com", age: 25 }; // ❌ Mist 'email'? Error! const badUser: User = { id: 2, name: "Bob", age: 30 }; // ERROR: Property 'email' is missing // ❌ Typo in property name? const typoUser: User = { id: 3, name: "Charlie", emial: "charlie@example.com", // TYPO! age: 28 }; // ERROR: 'emial' doesn't exist, did you mean 'email'? ``` ### Docentnotities Tim is enthousiast over interfaces want ze zijn core van TypeScript. "Dit is het HART van TypeScript. Interfaces. Een interface is als een blauwdruk. Je zegt: 'als je deze interface wil gebruiken, MOET je deze properties hebben, met deze types.' En als je het mist, weet TypeScript het DIRECT. Kijk naar dit voorbeeld. User-interface heeft id, name, email, age. Ze moeten allemaal exact zo heten, met exact die types. Nu, wat als je email vergeet? ERROR. TypeScript zegt: 'Sorry, je mist email.' Fout voorkomen! En wat als je een typo maakt? OOK ERROR. TypeScript is zelfs slim genoeg om te zeggen: 'Ik zie 'emial', bedoel je 'email'?' Dit is super krachtig. Je codebase wordt much meer reliable." --- ## Slide 12: Optional Properties - De ? Syntax ### Op de Slide ```typescript // Niet alles is altijd verplicht interface Product { id: number; name: string; description?: string; // Optional! discount?: number; // Optional! } // Dit werkt: nur verplichte velden const product1: Product = { id: 1, name: "Laptop" }; // Dit ook: plus optionele velden const product2: Product = { id: 2, name: "Mouse", description: "Wireless mouse", discount: 10 }; // ❌ Dit niet: naam is verplicht! const badProduct: Product = { id: 3, description: "Some product" }; // ERROR: Property 'name' is missing ``` ### Docentnotities Tim legt uit hoe je dingen optioneel maakt. "Niet alles in een object is altijd nodig. Soms kan iets leeg zijn. Daar is de `?` voor. `description?` betekent: dit mag voorkomen of niet. Maakt niet uit. Dus je kunt een Product maken zonder description. Dat's fijn. Maar je MOET nog steeds `name` hebben. Dit geeft je flexibiliteit terwijl je toch veilig blijft. Best of both worlds." --- ## Slide 13: Interface vs Type - Wanneer Welke? ### Op de Slide | **Interface** | **Type** | |---|---| | Voor objecten | Voor unions, primitives | | Extensible (kan meerdere keren gedefinieerd worden) | Niet extensible | | `interface User { ... }` | `type User = { ... }` | | Beter voor OOP-style code | Beter voor functional style | **Regel van Thumb:** - Objects → Interface - Unions, strings, numbers → Type - Doubt? → Interface ```typescript // Interface: objects interface User { name: string; email: string; } // Type: unions type Status = "active" | "inactive" | "pending"; type Direction = "north" | "south" | "east" | "west"; // Type: primitives type ID = string | number; // Kan string OF getal zijn ``` ### Docentnotities Tim legt het onderscheid uit. "Jullie gaan twee dingen zien: interfaces en types. Waarom twee? Interface is voor objecten. Als je een object wil definiëren — userstructure, product-shape — interface. Type is voor alles anders. Unions, literal types, primitives. Eigenlijk, laat me voorzichtig zijn: je KUNT alles met type doen. Maar interfaces zijn duidelijker voor objects. Dus hier is mijn regel: Objects? Interface. Alles anders? Type. Twijfel? Interface. Veel TypeScript-code volgt dit. En we doen dit ook in de escaperoom." --- ## Slide 14: Type Aliases & Union Types ### Op de Slide ```typescript // Type alias: geef een type een naam type Status = "pending" | "approved" | "rejected"; // Nu kun je het gebruiken function handleStatus(status: Status) { if (status === "pending") { console.log("Still processing..."); } else if (status === "approved") { console.log("All good!"); } else if (status === "rejected") { console.log("Denied."); } } handleStatus("pending"); // ✅ OK handleStatus("approved"); // ✅ OK handleStatus("rejected"); // ✅ OK handleStatus("foo"); // ❌ ERROR! // Union types: iets kan MEERDERE types zijn type Result = string | number; function processResult(result: Result) { if (typeof result === "string") { console.log(result.toUpperCase()); } else { console.log(result.toFixed(2)); } } processResult("hello"); // ✅ String processResult(42); // ✅ Getal processResult(true); // ❌ ERROR, boolean niet allowed ``` ### Docentnotities Tim combineert beide concepten en laat zien hoe ze samenwerken. "Type alias: je geeft een type een naam. `Status` is nu een type. Dat's handig — je kunt het overal gebruiken. En union types: het vet. Het zegt: dit kan string, of number, of alles wat je zegt. Waarom is dit cool? Omdat je dan code schrijft die ZEGT: 'ik accepteer strings of getallen, niet meer.' Als iemand anders je code aanroept met boolean, krijgen ze error. Veiligheid. Maar let op: zodra je iets doet wat alleen op string werkt — `.toUpperCase()` — moet je EERST checken of het een string is. Anders error. We komen hier later op terug (narrowing). Maar the point: unions geven je controle." --- ## Slide 15: Literal Types - Specifiekere Types ### Op de Slide ```typescript // Literal types zijn specifieker dan string/number // Je beperkt de mogelijke waarden tot exact die waarden type Direction = "north" | "south" | "east" | "west"; type DiceRoll = 1 | 2 | 3 | 4 | 5 | 6; type Toggle = true | false; // boolean is eigenlijk ook literals // Vergelijking: ZONDER literal types function move(direction: string) { console.log(`Moving ${direction}`); } move("north"); // ✅ OK move("south"); // ✅ OK move("banana"); // ✅ GEEN ERROR! String = string move("left"); // ✅ GEEN ERROR! String = string // Dit is slecht. Je accepteert alles. // MET literal types function moveProper(direction: Direction) { console.log(`Moving ${direction}`); } moveProper("north"); // ✅ OK moveProper("south"); // ✅ OK moveProper("banana"); // ❌ ERROR! moveProper("left"); // ❌ ERROR! // Much beter. Je accepteert ALLEEN wat je wil. // Praktijk voorbeeld type HttpMethod = "GET" | "POST" | "PUT" | "DELETE" | "PATCH"; function makeRequest(method: HttpMethod, url: string) { fetch(url, { method }); } makeRequest("GET", "https://api.example.com"); // ✅ makeRequest("GETT", "https://api.example.com"); // ❌ ERROR! ``` ### Docentnotities Tim is enthousiast en benadrukt waarom dit belangrijk is. "NEW CONCEPT: literal types. Dit is geweldig. Begrijp dit: je kunt niet alleen zeggen 'dit is een string'. Je kunt zeggen 'dit is een string, maar ALLEEN deze strings'. Dus `Direction` kan `"north"`, `"south"`, `"east"`, of `"west"` zijn. Niks anders. Waarom is dit beter dan `string`? Omdat je fouten voorkoomt. Als je `moveProper("banana")` doet, TypeScript zegt: 'Nope, banana is geen richting.' Praktisch: in je API, je hebt GET, POST, PUT, DELETE. Dit zijn de ENIGE geldige HTTP-methoden. Dus je definiëert dit met literal types. Nu kan code die je functie aanroept niet per ongeluk `GETT` door geven. Dit voorkomen mistakes. En it's één van mijn favoriete TypeScript-features. Dus remember: als je waarden beperkt zijn, use literals. Niet `string`." --- ## Slide 16: Type Narrowing - TypeScript Wordt Slimmer ### Op de Slide ```typescript // Probleem: union type, maar je weet niet wat het is function processValue(value: string | number) { // Hier weet TypeScript niet: is dit string of number? console.log(value.toUpperCase()); // ❌ ERROR! // 'number' has no property 'toUpperCase' // TypeScript stelt zich voorzichtig op } // Oplossing: TypeScript 'narrowing' // Na een check, wordt TypeScript SLIM function processValueSmart(value: string | number) { // TypeScript weet nog steeds niet wat het is // Maar na deze check... if (typeof value === "string") { // Hier weet TypeScript: dit is een STRING console.log(value.toUpperCase()); // ✅ OK! } else { // Hier weet TypeScript: dit is een NUMBER (enige alternative) console.log(value.toFixed(2)); // ✅ OK! } } processValueSmart("hello"); // ✅ processValueSmart(42.5); // ✅ // Ander voorbeeld function formatValue(val: string | number | boolean): string { if (typeof val === "string") { return val.toUpperCase(); } else if (typeof val === "number") { return val.toFixed(2); } else { return val ? "YES" : "NO"; } } ``` ### Docentnotities Tim legt narrowing uit als één van de kernconcepten. "Dit is belangrijk. Echt belangrijk. Union types zeggen: 'Dit kan dit of dat zijn.' Maar dan, als je iets wil DOEN met dat value, weet TypeScript niet welke methods je kunt gebruiken. String heeft `toUpperCase()`, number niet. Dus TypeScript blocks je. Conservatief. Maar kijk hier: na een `typeof` check, wordt TypeScript SLIM. Het zegt: 'Oké, je hebt gecheck dat het een string is. In deze branch, weet ik zeker: het is een string.' Daarom werkt `.toUpperCase()` dan wel. Dit heet type narrowing. Je 'narrows' de mogelijkheden down. Dit is super krachtig. Je schrijft veilige code want TypeScript helpt je. En je flexibiliteit blijft — je kunt MEERDER types accepteren, je moet je just voorzichtig zijn hoe je ze gebruikt. Dit pattern zie je OVERAL in TypeScript. Dus remember het." --- ## Slide 17: Type Guards - Veilig Checken ### Op de Slide ```typescript // Type guards: verschillende technieken om types te checken // 1) typeof voor primitives function formatValue(value: string | number | boolean): string { if (typeof value === "string") { return value.toUpperCase(); } if (typeof value === "number") { return value.toFixed(2); } return value ? "Yes" : "No"; } // 2) 'in' operator voor object properties interface Dog { bark(): void; breed: string; } interface Cat { meow(): void; color: string; } function makeSound(animal: Dog | Cat): void { // Check: heeft het 'bark' method? if ("bark" in animal) { animal.bark(); // TypeScript weet: dit is Dog } else { animal.meow(); // TypeScript weet: dit is Cat } } // 3) instanceof voor classes (komende lessen) class User { name: string; constructor(name: string) { this.name = name; } } class Admin extends User { permissions: string[]; constructor(name: string, perms: string[]) { super(name); this.permissions = perms; } } function getRole(person: User | Admin): string { if (person instanceof Admin) { return `Admin with ${person.permissions.length} permissions`; } return `Regular user: ${person.name}`; } // 4) Literale checks type Status = "pending" | "approved" | "rejected"; function handleStatus(status: Status): void { if (status === "pending") { console.log("Wait..."); } else if (status === "approved") { console.log("Great!"); } else { console.log("No."); } } ``` ### Docentnotities Tim laat zien dat er veel manieren zijn om types te checken. "Type guards zijn manieren om TypeScript te helpen bepalen wat het type is. We hebben al `typeof` gezien. Dat werkt voor primitives: string, number, boolean, etcetera. Dan is er `in` — je check: bestaat deze property? Handig voor objects. Als `animal` heeft `bark`, het's een Dog. Geen `bark`? Cat. `instanceof` gebruiken we binnenkort (met classes). Dat zeggen we: is dit een instantie van deze class? En literals: je checkt op exact waarde. `status === "pending"`. Allemaal useful. TypeScript staat erom bekend dat het, als je één van deze checks doet, automatisch het type 'snapt' in die branch. Heel slim. Dit is real-world pattern. Je zult dit veel gebruiken." --- ## Slide 18: Intersection Types - Types Combineren ### Op de Slide ```typescript // Intersection types: combineer types met & // & betekent: BEIDE vereisten moeten voldaan zijn (AND) // (Onthoud: | betekent OR, & betekent AND) type HasName = { name: string; }; type HasAge = { age: number; }; // Intersection: moet BEIDE hebben type Person = HasName & HasAge; // Dit object moet BEIDE types satisfyen const person: Person = { name: "Alice", age: 25 // Als je één mist → ERROR }; // Praktisch voorbeeld interface Timestamped { createdAt: Date; updatedAt: Date; } interface User { id: number; name: string; email: string; } // Combineer ze type TimestampedUser = User & Timestamped; const user: TimestampedUser = { id: 1, name: "Bob", email: "bob@example.com", createdAt: new Date("2024-01-01"), updatedAt: new Date("2024-03-05") }; // TimestampedUser heeft nu: id, name, email, createdAt, updatedAt // All required! // Vergelijking: Union vs Intersection type StringOrNumber = string | number; // Kan één van beide zijn type StringAndNumber = string & number; // Kan beide zijn (eigenlijk nooit) // Praktisch interface Admin { adminLevel: number; canDelete: boolean; } interface User2 { username: string; email: string; } function grantAdminAccess(user: User2 & Admin) { console.log(`${user.username} is now admin level ${user.adminLevel}`); } ``` ### Docentnotities Tim legt intersection uit en vergelijkt met union. "Intersection types. De tegenpool van unions. Union (`|`): dit OF dat. Intersection (`&`): dit EN dat. Met intersection zeg je: dit object MOET BEIDE types satisfyen. If je Person & Admin bent, je bent person EN je bent admin. Praktijk: stel je hebt een `Timestamped` interface — iets createdAt, updatedAt. En je hebt `User` — id, name, email. Now je wil een User die ook Timestamped is. Dit is waar intersection handig is: `User & Timestamped`. Iemand die diese type ontvangt weet: dit object heeft ALles van User PLUS alles van Timestamped. Dit combineert de sterke punten van beide. Neat feature." --- ## Slide 19: Readonly & Tuples ### Op de Slide ```typescript // READONLY: maak dingen immutable interface Config { readonly apiUrl: string; readonly port: number; debug: boolean; // Deze CAN wijzigen } const config: Config = { apiUrl: "https://api.example.com", port: 3000, debug: true }; config.debug = false; // ✅ OK - niet readonly config.apiUrl = "other"; // ❌ ERROR! // Cannot assign to 'apiUrl' because it is a read-only property. // Waarom? Veiligheid. Sommige dingen mogen niet veranderen. // TUPLES: arrays met vaste lengte en types type Coordinate = [number, number]; const point: Coordinate = [10, 20]; // ✅ const wrong: Coordinate = [10, 20, 30]; // ❌ Tuple type has 2 elements const invalid: Coordinate = [10, "twenty"]; // ❌ Type 'string' is not assignable to 'number' // Tuple met named elements type User3 = [id: number, name: string, email: string]; const user: User3 = [1, "Alice", "alice@example.com"]; // ✅ // Access: user[0] = id, user[1] = name, user[2] = email // React-example (preview!) // useState returnt een tuple: [value, setValue] type UseStateReturn = [T, (value: T) => void]; function useState(initial: T): UseStateReturn { // ... implementation return [initial, (newVal) => { /* set it */ }]; } const [count, setCount] = useState(0); // count is number, setCount is (value: number) => void ``` ### Docentnotities Tim legt readonly en tuples uit, met preview op React. "Twee nieuwe concepten: readonly en tuples. Readonly: je kunt iets niet veranderen. Waarom? Soms zijn dingen veilig — je config URL moet niet zomaar veranderd worden. readonly helpt dit af te dwingen. `readonly apiUrl: string` — dit kan nooit veranderd worden. TypeScript blokkeert het. Tuples: arrays met vaste lengte en types. In plaats van `[1, 2, 3]` waar elk element number kan zijn, kun je zeggen: eerste element number, tweede element string, derde element boolean. Waarom? Omdat dan je code is very specific. Je weet PRECIES wat je hebt. Quick preview: in React, `useState` returnt een tuple: het huuidswaarde, en de setter function. Die tuple heeft vaste structuur: [value, setter]. Dat's waarom je `const [count, setCount] = useState(0)` kunt doen. Tuples zijn dus useful, en je gaat ze snel gebruiken." --- ## Slide 20: Functies Typen - Parameters & Return ### Op de Slide ```typescript // Functies hebben types: parameters en return value // Basic function add(a: number, b: number): number { return a + b; } add(5, 3); // ✅ 8 add(5, "3"); // ❌ ERROR // Arrow functions (zelfde typering) const multiply = (a: number, b: number): number => { return a * b; }; // Optional parameters function greet(name: string, greeting?: string): string { return (greeting ?? "Hello") + ", " + name; } greet("Alice"); // ✅ "Hello, Alice" greet("Bob", "Good morning"); // ✅ "Good morning, Bob" // Void: geen return value function logError(message: string): void { console.error(message); } logError("Oops!"); // ✅ const result = logError("Oops!"); // result is undefined // Union return types function processInput(input: string | number): string { if (typeof input === "string") { return input.toUpperCase(); } return input.toFixed(2); } // Promise return type (async, meer later) async function fetchUser(id: number): Promise { const response = await fetch(`/api/users/${id}`); return response.json(); } // Function types als parameters function applyOperation( a: number, b: number, operation: (x: number, y: number) => number ): number { return operation(a, b); } applyOperation(10, 5, (x, y) => x + y); // ✅ 15 applyOperation(10, 5, (x, y) => x - y); // ✅ 5 applyOperation(10, 5, (x, y) => x * y); // ✅ 50 ``` ### Docentnotities Tim legt alle type-aspecten van functies uit. "Functies. Al de basis-functie-dingen maar nu met types. Parameters: je zegt wat elke parameter moet zijn. `a: number, b: number` — twee getallen. Return type: je zegt wat je teruggeeft. `: number` — je geeft een getal terug. Optional parameters: `greeting?` — dit hoeft niet. Als je het niet megeeft, is het undefined. Je kunt `??` gebruiken om een default in te stellen. Void: je returnt niks. Heel handig voor functions die side-effects doen — log een bericht, update de database, whatsoever. Union returns: je kunt meerdere types returnen, zolang je het zegt. Promise: voor async functies. We doen dit veel meer in volgende lessen. Maar the idea: dit returnt een Promise die eventually een User geeft. En hier's cool: functies als parameters. Als je een function als parameter neemt, type je dat ook. `(x: number, y: number) => number` — dit is een function die twee getallen ontvangt en een getal teruggeeft. Dit zie je veel bij array-methoden zoals `map`, `filter`. We doen dat snel." --- ## Slide 21: Functies met Generics - Een Preview ### Op de Slide ```typescript // Het probleem: functies voor specifieke types // Dit werkt alleen voor getallen function firstItemNumbers(items: number[]): number { return items[0]; } // Dit werkt alleen voor strings function firstItemStrings(items: string[]): string { return items[0]; } // Dit werkt alleen voor Users function firstItemUsers(items: User[]): User { return items[0]; } // Heel repetitief. Bad! // ======================================== // De oplossing: Generics (placeholders voor types) // ======================================== // T = "Type parameter" — placeholder voor ANY type function firstItem(items: T[]): T { return items[0]; } // Nu werkt dit voor ALLES const num = firstItem([1, 2, 3]); // T = number const str = firstItem(["a", "b", "c"]); // T = string const user = firstItem([alice, bob]); // T = User // TypeScript raadt T automatisch! // Je hoeft niet eens te zeggen wat het is. // Meer complex voorbeeld function getProperty(obj: T, key: K): T[K] { return obj[key]; } const obj = { name: "Alice", age: 25 }; const name = getProperty(obj, "name"); // string const age = getProperty(obj, "age"); // number const invalid = getProperty(obj, "email"); // ❌ ERROR - email bestaat niet // Of met arrays function findById(items: T[], id: number): T | undefined { return items.find(item => item.id === id); } const users: User[] = [ { id: 1, name: "Alice", email: "alice@example.com" }, { id: 2, name: "Bob", email: "bob@example.com" } ]; const found = findById(users, 1); // T = User, returnt User | undefined ``` ### Docentnotities Tim introduceert generics als preview voor volgende les. "Dit is een PREVIEW. Generics komen echt in Les 5, maar ik wil dat jullie het concept begrijpen. Stel je hebt een simpele functie: gee mij het eerste item van een array. Makkelijk. Maar: wat als je een array van nummers hebt? number. Array van strings? string. Array van Users? User. Je zou normaal drie functies moeten schrijven. Repetitief. Bad. Generics: je zegt: 'Ik weet niet WELKE type, maar hoe je het ook geeft, ik behandel het op dezelfde manier.' `T` is een placeholder. Het betekent: whatever type je geeft. Dus `firstItem` werkt voor getal-arrays, string-arrays, alles. En het coolist: TypeScript RAADT het. Je zegt niet `firstItem`. Je zegt gewoon `firstItem([1, 2, 3])` en TypeScript weet: T moet number zijn. Dit is super krachtig. Veel modern TypeScript maakt generics. Volgende week gaan we dit echt uitdiepen. Maar the point: generics = flexibiliteit zonder type safety verlies." --- ## Slide 22: Veelvoorkomende Errors - Top 5 ### Op de Slide ``` 1️⃣ Type Mismatch const num: number = "hello"; // ❌ Type 'string' is not assignable to type 'number' Fix: Zorg dat types matchen 2️⃣ Missing Property const user: User = { id: 1, name: "Alice" }; // ❌ Property 'email' is missing in type '{...}' Fix: Voeg alles toe wat interface verwacht, of maak optioneel (?) 3️⃣ Object is possibly undefined function getAge(user: User | undefined) { console.log(user.age); // ❌ Object is possibly 'undefined' } Fix: Check eerst: if (user) { ... } 4️⃣ Argument not assignable to union type type Status = "pending" | "approved" | "rejected"; const status: Status = "pending"; const status2: Status = "foo"; // ❌ Type '"foo"' is not assignable to type 'Status' Fix: Gebruik alleen de allowed values 5️⃣ Property does not exist on type const user: User = { ... }; console.log(user.emial); // Typo! // ❌ Property 'emial' does not exist on type 'User' Fix: Spel correct, of gebruik autocomplete ``` ### Docentnotities Tim gaat door de meeste fouten die students zien. "Oké, top 5 fouten die jullie gaan maken. En dat's okay — iedereen doet het. Eén: type mismatch. Je zegt number, je geeft string. Fout. Fix: types laten matchen. Twee: missing property. Je interface zegt: dit object moet deze velden hebben. Je geeft er maar drie. Vier ervan ontbreken. Fout. Fix: voeg alles toe, of maak optional. Drie: object is possibly undefined. Je hebt `User | undefined`, je probeert `.age` aan te roepen. Misschien is het undefined! Fout. Fix: check eerst. Vier: argument not assignable to union type. Je hebt een union van strings: "pending", "approved", "rejected". Je geeft "foo". Fout. Fix: één van de allowed values gebruiken. Vijf: property does not exist. Meestal een typo. `emial` in plaats van `email`. TypeScript ziet dit. Fix: spel correct, of type punt en laat autocomplete je helpen. Allemaal super common. Allemaal easy te fixen. Allemaal zijn ze TypeScript's way om je te beschermen." --- ## Slide 23: Cursor + TypeScript - Superkrachten ### Op de Slide - **IntelliSense**: Typ punt, zie alle methods/properties - **Error Underlines**: Rode squiggly lines onder problemen (hover om te zien) - **Go to Definition**: Ctrl/Cmd + Click op een naam, spring naar definitie - **Refactor**: Select code, refactor menu, rename overal - **Hover Info**: Hover over anything, zie het type/documentatie **Golden Rule**: "Read the error messages! They help you." ### Docentnotities Tim benadrukt hoe powerful Cursor + TypeScript is. "Cursor + TypeScript = superkrachten in je editor. Autocomplete: je typt `user.` en je editor zegt: hier kunnen `id`, `name`, `email` zijn. Je hoeft niet het hele ding uit je hoofd te weten. Error underlines: je ziet rode lijnen, je weet direct: hier is iets fout. Hover: je hovert over een variabele en je ziet: dit is een `string`, dit is een `User`, whatever. Go to definition: je ziet een functie, je Cmd+klikt, en je bent in de definitie. Super handig om code te verstaan. Refactoring: je wil `username` hernoemen naar `name`. Je selecteert, refactor menu, rename all occurrences. TypeScript vindt alles. Zero fouten. De key: **read the error messages**. Ze zijn NOT cryptic. Ze zeggen precies wat fout is en hoe je het fixt. Niemand here memorized alle error messages. Niemand. We lezen ze. Dus: lees. Dit voelt als programmeren met een copilot. Heel cool." --- ## Slide 24: Escaperoom Introductie ### Op de Slide **TypeScript Escaperoom: 10 Kamers** 🟢 **Easy (Kamers 1-2)** - Kamer 1: Basic Types & Type Inference - Kamer 2: Arrays & Simple Interfaces 🟢 **Easy-Medium (Kamers 3-4)** - Kamer 3: Interfaces & Properties - Kamer 4: Optional Properties & Defaults 🟡 **Medium (Kamers 5-6)** - Kamer 5: Union Types & Type Aliases - Kamer 6: Literal Types & Exhaustive Checks 🟠 **Hard (Kamers 7-8)** - Kamer 7: Type Narrowing & Type Guards - Kamer 8: Function Types & Callbacks 🔴 **Very Hard (Kamers 9-10)** - Kamer 9: Intersection Types & Readonly - Kamer 10: **BOSS ROOM** - Complex typing challenges **Target**: Minstens kamers 1-6 halen. Kamers 7-10 zijn bonus. ### Docentnotities Tim introduceert de escaperoom met enthousiasme. "Oké, nu het leuke gedeelte. Escaperoom. Je hebt tien kamers voor je. Elk met een ander TypeScript-probleem. Je begint easy, het wordt harder. Kamer 1: basis. Typen, inference. Warm-up. Kamers 2, 3, 4: nog makkelijk maar starter concepten. Arrays, interfaces, optionele velden. Kamers 5, 6: union types, literal types. Medium. Kamers 7, 8: narrowing, guards. Harder. Kamers 9, 10: intersection, readonly, boss room. Lastig. Mijn doel voor jullie: haal minstens kamers 1 tot 6. Dat's basisheheersen. Kamers 7 tot 10? Bonus. Als je tijd hebt, probeer. Maar 1-6 is het doel. Dit is hands-on. Je gaat TYPEN. Je gaat ERRORS FIXEN. Je gaat echt TypeScript leren. Veel beter dan slides." --- ## Slide 25: Escaperoom Rules & Structuur ### Op de Slide **De Regels:** 1. ✅ **AI OFF**: - Cmd+Shift+P → "Disable Cursor Tab" - Je moet ZELF nadenken - Dit is de punt 2. ✅ **Geen `any`** - Niet `any: any` - Niet `value as any` - TypeScript helpen! Als je stuck bent, ask Tim 3. ✅ **Type checking** - Code moet compileren WITHOUT errors - Rode squigglies moeten weg 4. ✅ **Communiceer** - Stuck? Roep Tim! 🙋 - Iemand else hier dit net opgelost? Help elkaar! 5. ✅ **Timing** - ~50-60 minuten totaal - Niet alles moet af - Minimaal 1-6, bonus 7-10 ### Docentnotities Tim legt de escaperoom-regels duidelijk uit. "Escaperoom regels. Important. Eén: AI OFF. Nu, je maakt allemaal misbruik van AI in je werk — ik snap het, het's super handig. Maar hier: uit. Je MOET zelf nadenken. Dit is hoe je echt leert. Als je stuck bent, check je error message. Lees het. Denk. Experiment. Vraag Tim. Twee: geen `any`. Serieus. If je `any` gebruikt, je hebt verloren. TypeScript helpen. Figuur het type uit. Dat's de point. Drie: code moet compileren. Geen rode errors. Allemaal weg. Vier: communiceer. Stuck? Roep! Iemand els hier een solution? Help elkaar. We're een team. Vijf: timing. Je hebt 50 tot 60 minuten. Je hoeft niet alles af te hebben. Doel: minstens 1-6. Let me be clear: dit is het VAN de les. Slides zijn prep. Dit — hands-on problem solving — dit's where it's at. Dus: focus. AI uit. Think hard. Let's goooo!" --- ## Slide 26: Samenvatting - Key Takeaways ### Op de Slide **6 Key Takeaways van Les 4:** 1. **TypeScript vangt fouten VOORDÁT je code draait** - JavaScript accepts anything, TypeScript is strict - Better safe than sorry in production 2. **Types zijn documentatie** - Je code zegt waar het voor is - Minder comments nodig, meer duidelijkheid 3. **Basics: types, arrays, interfaces, unions** - These are the foundation - Alle ander bouwt hierop 4. **Geavanceerd: narrowing, guards, intersection, readonly** - These make you a real TypeScript developer - You control your types precisely 5. **Generics zijn the future (Les 5)** - Flexibiliteit met type safety - Preview gezien, deep-dive next week 6. **Cursor + TypeScript = superkrachten** - Autocomplete, error messages, refactoring - Read the messages, they help you ### Docentnotities Tim doet een energieke samenvatting. "Okay, let me wrap up. Zes dingen om mee te nemen. Eén: TypeScript vangt fouten. JavaScript zwijgt en doet raar spul. TypeScript zegt: nope, niet gebeurd. Twee: types zijn self-dokumenting. Je ziet `function fetchUser(): Promise` en je WEET wat dit doet. Drie: basis stuff. Alles bouwt hierop. As je dit niet hebt, volgende weken gaat pijn doen. Vier: geavanceerd spul. Narrowing, guards, intersection, readonly. Dit maakt je TypeScript Developer Level Expert. Vijf: generics. Dit week preview. Volgende week DEEP. Het's gonna blow your mind. Zes: Cursor. Je editor is je beste vriend. Het helpt je. Luister ernaar. Als je één ding van deze les meeneemt: **types voorkomen bugs**. Alles else is details." --- ## Slide 27: Huiswerk & Preview Les 5 ### Op de Slide **Huiswerk: JavaScript → TypeScript Converter** - Download `les4-huiswerk-js-converter.zip` van Teams - Zet 4 JavaScript bestanden om naar TypeScript: - `users.js` → `users.ts` (User interface, CRUD functies) - `products.js` → `products.ts` (Product interface, union types) - `orders.js` → `orders.ts` (Order interface, status management) - `utils.js` → `utils.ts` (Generics: sortBy, groupBy) - Schrijf interfaces, union types, typed functies - `npm run check` = 0 errors, `npm test` = alle 26 tests groen - Geen `any` toegestaan! **Preview Les 5 - TypeScript voor React:** - Generics & utility types (Partial, Pick, Omit, Record) - Props & state typen in React - Event handlers & async functies typen - API responses typen met `Promise` ### Docentnotities Tim sluit af met huiswerk en preview. "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`! Dit kost je anderhalf tot twee uur. Nee, je kan niet skippen. Waarom? Omdat volgende week GENERICS zijn. En generics BOUWEN op wat jullie deze week leren. 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. Dus zorg dat je huiswerk doet — je hebt die basis nodig. Goed werk vandaag! Tot volgende keer!" --- --- # Aanvullende Notities voor Tim ## Timing & Flow **Totaal: 180 minuten** - Blok 1 (20 min): 0:00-0:20 Het Probleem & De Oplossing - Blok 2 (25 min): 0:20-0:45 Type Basics - Blok 3 (20 min): 0:45-1:05 Geavanceerde Types - **PAUZE (15 min): 1:05-1:20** ☕ - Blok 4 (50-60 min): 1:20-2:20 Escaperoom - Afsluiting (15 min): 2:20-2:35 Samenvatting, huiswerk, preview Dit geeft **65-70 minuten talking time** (Blok 1-3 + Afsluiting) en **50-60 minuten hands-on escaperoom**, exact zoals gevraagd. ## Interactie-suggesties **Blok 1:** - Slide 4: Poll: "Who's seen this bug before?" (hand raising) - Slide 6: Name one TypeScript user: "Netflix, Airbnb, who else uses it in your code?" **Blok 2:** - Slide 8: Live code in Cursor — type variables, hover to see types - Slide 11: Ask: "What happens if we forget a property?" then show error - Slide 12: "Can anyone guess what ? does?" before revealing **Blok 3:** - Slide 15: Poll on literal types — "Which is safer: `string` or `Direction`?" - Slide 16: Trace through narrowing example together — "After this check, what does TypeScript know?" - Slide 19: Show readonly error in Cursor, let students gasp **Escaperoom:** - Encourage pair programming ("Team up if you want") - Check-in at Kamer 5 — if most people passed, adjust difficulty messaging - Celebrate wins — "You got Kamer 7! 🎉" ## Mogelijke vragen van students **Q: Why do I need to type everything? Isn't this verbose?** A: Not at all. TypeScript catches bugs JavaScript misses. And it's not verbose — hover in your editor, let autocomplete help. You get accuracy + speed. Best both worlds. **Q: Can I use `any`?** A: NO. Serieus. Any defeats the point of TypeScript. If you can't figure the type, ask me. We'll find it together. **Q: Union types are confusing. How do I know which one I have?** A: That's what narrowing and guards are for. Checken, and TypeScript knows. Practice it. **Q: Do I need to memorize all these rules?** A: No. Your editor tells you. Read error messages — they're your friend. **Q: How is this different from just using JSDoc?** A: JSDoc is comments. TypeScript is enforced. TypeScript actually stops you from running bad code. JSDoc doesn't. **Q: Will Generics in Les 5 be hard?** A: Yes. But you're ready. Today you learned the foundation. Next week, we build on it. ## Code examples best practices (voor live coding) 1. **Start simple, build up**: Don't paste entire examples. Type piece by piece, let errors appear, fix them. 2. **Make mistakes on purpose**: Forget a property, show the error, fix it. This is how people learn. 3. **Use Cursor's features**: Hover to show types, use autocomplete, let TypeScript guide you. 4. **Explain error messages**: Don't just fix them silently. Say: "TypeScript says... and here's why..." 5. **Reference past examples**: When you show unions, reference interfaces from earlier. Build context. ## Escaperoom 10-kamer structuur **Kamer 1**: Basic types in variables ```typescript // Assign correct types to variables const name: ??? = "Alice"; const age: ??? = 25; ``` **Expected**: `string`, `number` — warm up **Kamer 2**: Array typing ```typescript // Type these arrays const scores = [10, 20, 30]; const names = ["Alice", "Bob"]; ``` **Expected**: `number[]`, `string[]` **Kamer 3**: Interface basics ```typescript // Define interface and fix the object interface User { ??? } const user: User = { id: 1, name: "Alice", email: "alice@example.com" }; ``` **Expected**: Proper interface definition **Kamer 4**: Optional properties ```typescript interface Product { id: number; name: string; ??? } const product: Product = { id: 1, name: "Laptop" }; // no description ``` **Expected**: `description?: string` **Kamer 5**: Union types ```typescript type Status = "pending" | "done" | "error"; function handle(status: Status) { ??? } handle("pending"); // ✅ handle("foo"); // ❌ fix this ``` **Expected**: Use correct Status value **Kamer 6**: Literal type narrowing ```typescript function move(direction: "north" | "south" | "east" | "west") { ??? } move("north"); // ✅ move("left"); // ❌ fix this ``` **Expected**: Use correct literal **Kamer 7**: Type narrowing with typeof ```typescript function process(value: string | number) { if (???) { console.log(value.toUpperCase()); // This assumes string } } ``` **Expected**: `typeof value === "string"` **Kamer 8**: Type guards with 'in' operator ```typescript interface Dog { bark(): void; } interface Cat { meow(): void; } function sound(animal: Dog | Cat) { if (???) { animal.bark(); } else { animal.meow(); } } ``` **Expected**: `"bark" in animal` **Kamer 9**: Readonly properties ```typescript interface Config { readonly apiUrl: string; debug: boolean; } const config: Config = { apiUrl: "...", debug: true }; config.debug = false; // ✅ config.apiUrl = "new url"; // ❌ fix this ``` **Expected**: User realizes `readonly` prevents reassignment, removes second assignment **Kamer 10 (BOSS)**: Complex intersection + narrowing ```typescript interface Timestamped { createdAt: Date; updatedAt: Date; } interface Entity { id: number; name: string; } type Document = Timestamped & Entity; function process(doc: Document | undefined) { if (???) { console.log(doc.id, doc.createdAt); } } ``` **Expected**: `doc !== undefined` (narrowing to verify it's not undefined before accessing properties) ## Tips for Tim 1. **Energy**: Les 4 is heavier than Les 3. Keep energy up during Blok 1-3 so students stay engaged. 2. **Live coding**: Don't just talk. Type. Let students see Cursor's intelligence. This motivates them. 3. **Pauze**: At 1:05, take a real break. Let students stretch, bathroom, water. They'll thank you. 4. **Escaperoom**: Circulate. Don't just sit at the front. Check in on students, offer hints, celebrate wins. 5. **Huiswerk**: Assign clearly. They NEED it for next lesson. 6. **Les 5 preview**: Generics sound scary. Reassure them: "You learned the foundation, next week is the application." ## Common student errors to watch for 1. Using `any` when stuck — remind them to ask or use error messages 2. Forgetting optional `?` when a property is sometimes missing 3. Union type usage without narrowing first 4. Spelling errors in property names — "emial" instead of "email" 5. Mixing up interface extends with intersection types (comes up in harder kamers) ## Success criteria for students - By end of Blok 3: Can explain why TypeScript matters - After escaperoom: Can fix 6-8 kamers - By Les 5: Did the JS→TS homework (you'll see this) --- End of Les04-Slide-Overzicht.md