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

6.1 KiB
Raw Blame History

Les 5: TypeScript voor React


Hoofdstuk

Deel 2: Technical Foundations (Les 4-9)

Beschrijving

Verdieping in TypeScript met focus op React-patronen. Studenten leren generics, utility types, en hoe je React components, hooks, events en API calls correct typt. Voorbereiding op Les 6 waar ze met Next.js aan de slag gaan.

Voorkennis: Les 4 (TypeScript Fundamentals) — basic types, interfaces, union types, type aliases, functies typen.


Te Behandelen

Generics (20 min)

  • Waarom generics? Herbruikbare, type-safe code
  • Array<T>, Promise<T> — generics die ze al kennen
  • Eigen generics schrijven: function getFirst<T>(items: T[]): T
  • Generics met constraints: <T extends { id: string }>
  • keyof operator: function getValue<T, K extends keyof T>(obj: T, key: K): T[K]
// Generic functie
function wrapInArray<T>(value: T): T[] {
  return [value];
}

wrapInArray("hello"); // string[]
wrapInArray(42);      // number[]

// Met constraint
function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {
  return obj[key];
}

Utility Types (15 min)

  • Partial<T> — alle properties optioneel (handig voor updates)
  • Pick<T, K> — selecteer specifieke properties
  • Omit<T, K> — alles behalve specifieke properties
  • Record<K, V> — key-value mapping
  • Praktisch voorbeeld: updateUser(id: string, data: Partial<User>)
interface User {
  id: string;
  name: string;
  email: string;
  age: number;
}

// Partial: voor update functies
function updateUser(id: string, updates: Partial<User>): User { ... }
updateUser("1", { name: "Tim" }); // alleen name updaten

// Omit: voor create functies (id wordt server-side gegenereerd)
type CreateUserInput = Omit<User, "id">;

// Pick: voor specifieke views
type UserPreview = Pick<User, "id" | "name">;

React Props Typen (20 min)

  • Interface voor component props
  • Children typen met React.ReactNode
  • Callback props: onClick: () => void, onChange: (value: string) => void
  • Spread props en prop forwarding
  • Default values met destructuring
interface CardProps {
  title: string;
  children: React.ReactNode;
  variant?: "default" | "highlighted";
  onClose?: () => void;
}

function Card({ title, children, variant = "default", onClose }: CardProps) {
  return (
    <div className={`card card-${variant}`}>
      <h2>{title}</h2>
      {onClose && <button onClick={onClose}>×</button>}
      {children}
    </div>
  );
}

useState & useEffect Typen (15 min)

  • Type inference bij useState: useState(0) → number
  • Explicit types: useState<User | null>(null)
  • Arrays: useState<Product[]>([])
  • useEffect met async patterns
const [user, setUser] = useState<User | null>(null);
const [products, setProducts] = useState<Product[]>([]);
const [loading, setLoading] = useState(false); // inference: boolean

useEffect(() => {
  async function fetchData() {
    setLoading(true);
    const response = await fetch("/api/users");
    const data: User[] = await response.json();
    setUsers(data);
    setLoading(false);
  }
  fetchData();
}, []);

Event Handlers Typen (10 min)

  • React.ChangeEvent<HTMLInputElement>
  • React.FormEvent<HTMLFormElement>
  • React.MouseEvent<HTMLButtonElement>
  • Tip: hover in Cursor om het juiste event type te vinden
function SearchForm() {
  const [query, setQuery] = useState("");

  const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    setQuery(e.target.value);
  };

  const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
    e.preventDefault();
    console.log("Searching:", query);
  };

  return (
    <form onSubmit={handleSubmit}>
      <input value={query} onChange={handleChange} />
    </form>
  );
}

API Responses & Async Typen (15 min)

  • Promise<T> voor async functies
  • API response types definiëren
  • Error handling met types
  • Fetch wrapper met generics
interface ApiResponse<T> {
  data: T;
  status: number;
  message: string;
}

async function fetchApi<T>(url: string): Promise<ApiResponse<T>> {
  const response = await fetch(url);
  if (!response.ok) {
    throw new Error(`HTTP error: ${response.status}`);
  }
  return response.json();
}

// Gebruik
const { data: users } = await fetchApi<User[]>("/api/users");
const { data: product } = await fetchApi<Product>("/api/products/1");

Tools

  • Cursor (Student Plan)
  • TypeScript
  • React (via CDN of Vite)

Lesopdracht (75 min)

Typed React Dashboard

Studenten bouwen een kleine React-app met volledig getypte components:

Opdracht: Bouw een Product Dashboard met:

  1. ProductCard component — props: Product interface, onAddToCart callback
  2. ProductList component — props: Product[], filterCategory (union type)
  3. SearchBar component — props: query string, onChange handler (getypt event)
  4. useProducts custom hook — fetch products, return { products, loading, error }
  5. Alle types in een apart types.ts bestand

Vereisten:

  • Geen any toegestaan
  • Alle event handlers correct getypt
  • useState met expliciete types waar nodig
  • Minstens 1 generic functie (bijv. een sortBy<T> of filterBy<T>)

Huiswerk (2 uur)

Extend het Dashboard

Bouw voort op de lesopdracht:

  1. Shopping Cart toevoegen met getypte state (CartItem[])
  2. API simulatie — maak een fetchProducts() functie met Promise<Product[]>
  3. Utility types gebruikenPartial<Product> voor updates, Omit<Product, "id"> voor create
  4. Bonus: Generic DataTable<T> component — werkt met elke array van objecten

Deliverable

  • Werkend React project met TypeScript
  • Alle components volledig getypt
  • npm run check = 0 errors

Leerdoelen

Na deze les kan de student:

  • Generics schrijven en toepassen
  • Utility types gebruiken (Partial, Pick, Omit, Record)
  • React component props correct typen
  • useState en useEffect met types gebruiken
  • Event handlers typen (ChangeEvent, FormEvent, MouseEvent)
  • Async functies en API responses typen met Promise
  • Een custom hook schrijven met correcte return types