6.1 KiB
6.1 KiB
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 }> keyofoperator: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 propertiesOmit<T, K>— alles behalve specifieke propertiesRecord<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:
ProductCardcomponent — props: Product interface, onAddToCart callbackProductListcomponent — props: Product[], filterCategory (union type)SearchBarcomponent — props: query string, onChange handler (getypt event)useProductscustom hook — fetch products, return{ products, loading, error }- Alle types in een apart
types.tsbestand
Vereisten:
- Geen
anytoegestaan - Alle event handlers correct getypt
- useState met expliciete types waar nodig
- Minstens 1 generic functie (bijv. een
sortBy<T>offilterBy<T>)
Huiswerk (2 uur)
Extend het Dashboard
Bouw voort op de lesopdracht:
- Shopping Cart toevoegen met getypte state (
CartItem[]) - API simulatie — maak een
fetchProducts()functie metPromise<Product[]> - Utility types gebruiken —
Partial<Product>voor updates,Omit<Product, "id">voor create - 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