Module 28: Interfaces and Type Design

Lesson 5 of 5 · 15–25 minutes

Designing types for a real app

🏠The everyday picture

An architect's drawing prevents a door opening into a wall before anything is built. Well-designed types prevent impossible situations before any code runs.

📘What it really is

// Weak: nothing stops paid: false with a paidAt date
interface Order { paid: boolean; paidAt?: string; refunded: boolean; }

// Strong: each state carries exactly what it needs
type OrderState =
  | { status: "pending" }
  | { status: "paid"; paidAt: string; payment: Payment }
  | { status: "refunded"; paidAt: string; refundedAt: string };

🖱️Try it

In types.ts, design the types for your inventory and expense manager: Product, Supplier, StockMovement (a discriminated union of "received", "sold" and "adjusted", each with what it needs), and Expense (with a literal union of categories). Write one line of comment above each explaining a rule it enforces.

✅Quick check

An order has paid: boolean and paidAt?: string. What impossible state can it represent?

Show the answer

paid: false with a paidAt date, or paid: true with no date. A discriminated union prevents both.

Why write types before asking AI to write the functions?

Show the answer

They define exactly what data exists and what's allowed; the AI's code is then checked against them.

← PreviousDiscriminated unions
ProLearners Assist