Files
novi-lessons/Les04-TypeScript-Fundamentals/Les04-Slide-Overzicht.md
2026-03-11 14:07:00 +01:00

49 KiB
Raw Blame History

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

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

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<Result>, 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

// 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

// Arrays van één type
const numbers: number[] = [1, 2, 3];
const colors: Array<string> = ["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<string> — 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

// 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

// 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

// 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
// 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

// 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

// 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

// 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

// 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

// 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

// 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> = [T, (value: T) => void];

function useState<T>(initial: T): UseStateReturn<T> {
  // ... 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

// 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<User> {
  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

// 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<T>(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<T, K extends keyof T>(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<T extends { id: number }>(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<T> werkt voor getal-arrays, string-arrays, alles.

En het coolist: TypeScript RAADT het. Je zegt niet firstItem<number>. 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<User> 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.jsusers.ts (User interface, CRUD functies)
    • products.jsproducts.ts (Product interface, union types)
    • orders.jsorders.ts (Order interface, status management)
    • utils.jsutils.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<T>

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

// Assign correct types to variables
const name: ??? = "Alice";
const age: ??? = 25;

Expected: string, number — warm up

Kamer 2: Array typing

// Type these arrays
const scores = [10, 20, 30];
const names = ["Alice", "Bob"];

Expected: number[], string[]

Kamer 3: Interface basics

// 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

interface Product {
  id: number;
  name: string;
  ???
}
const product: Product = { id: 1, name: "Laptop" }; // no description

Expected: description?: string

Kamer 5: Union types

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

function move(direction: "north" | "south" | "east" | "west") { ??? }
move("north");  // ✅
move("left");   // ❌ fix this

Expected: Use correct literal

Kamer 7: Type narrowing with typeof

function process(value: string | number) {
  if (???) {
    console.log(value.toUpperCase()); // This assumes string
  }
}

Expected: typeof value === "string"

Kamer 8: Type guards with 'in' operator

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

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

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