Level 3 · Programming Skills · Course 3.2 TypeScript

Module 28: Interfaces and Type Design

Goal: describe your app's data with named types and interfaces, and design types that make mistakes impossible to write, not just easy to spot.

You'll need: your inventory TypeScript project from Module 27.

Lessons

  1. 1Interfaces15–25 minutes✓
  2. 2Optional and readonly properties15–25 minutes✓
  3. 3Type aliases and when to use which15–25 minutes✓
  4. 4Discriminated unions15–25 minutes✓
  5. 5Designing types for a real app15–25 minutes✓

🛠️Module practice: Project D, part 2, the inventory model

  1. Complete types.ts from Lesson 5.
  2. Create sample data in data.ts for at least six products, two suppliers, ten stock movements and five expenses, fully typed.
  3. Write currentStock(productId, movements) that works out stock from the movements, using a switch on the movement type.
  4. npm run check passes with no any. Commit.

✅Module check

Explain in a few sentences, in your own words:

How do interfaces and discriminated unions help you design an app's data, and what does "make impossible states impossible" mean?

Show a good answer

A good answer mentions: interfaces (or object type aliases) name the shape of each thing in the app, so missing or misspelt properties are caught, with optional and readonly marking what may be absent or must never change. A discriminated union uses a shared literal property to describe each kind or stage of something with exactly the data it needs, and TypeScript checks every case is handled. Designing types so contradictory combinations (like "unpaid with a payment date") can't be written prevents bugs before any code exists.

📝Module quiz

10 questions · 10 marks each · 100 marks in all · pass mark 70% · retry as often as you like ·

1. What happens if a product object is missing a property its interface requires?

Why each option is right or wrong

  • “The missing property is filled in with a default value” (Incorrect): Interfaces don't add values. They only describe what must be there.
  • “The program crashes later, when the property is first used” (Incorrect): With the interface in place, TypeScript catches this before running.
  • “Nothing happens, since interfaces are only comments for people” (Incorrect): Interfaces are checked by the compiler; they're not just notes.
  • “TypeScript reports an error before the code runs” is correct.

    An interface lists the properties an object must have. If you create a product without one of them, the checker underlines it in your editor and tsc reports it, so the gap is fixed before the program ever runs.

    • Message: usually "Property 'price' is missing in type...".
    • Optional instead? Mark it with ? only if it really can be absent.

📖 Revise: Lesson 1: Interfaces

Question ID module-28-q1 · Report a mistake in this question
2. Why make an order's id readonly?

Why each option is right or wrong

  • “So the id is encrypted when stored in the database” (Incorrect): readonly is a type check. It has nothing to do with encryption.
  • “Readonly properties use less memory than normal ones” (Incorrect): Types are removed before running, so there's no memory difference.
  • “So the id can't be read by code in other files” (Incorrect): Readonly stops changes, not reading. Anyone can still read it.
  • “An id shouldn't change once created, and readonly enforces it” is correct.

    Other records, like payments and deliveries, refer to an order by its id. If code accidentally changed it, those links would break. readonly makes TypeScript report any attempt to reassign it.

    • Compile-time only: readonly is checked while writing, not enforced at run time.
    • Good candidates: ids, creation dates, anything set once.

📖 Revise: Lesson 2: Optional and readonly properties

Question ID module-28-q2 · Report a mistake in this question
3. Every customer must have a phone number. Should phone be optional?

Why each option is right or wrong

  • “Yes, optional properties are safer because nothing can break” (Incorrect): Optional means code must handle it being missing everywhere, and customers could be saved without one.
  • “Yes, so the form can be submitted before the phone is entered” (Incorrect): That would let customers be saved without phones, breaking the rule.
  • “It doesn't matter; TypeScript treats both exactly the same way” (Incorrect): They're treated differently: optional allows the property to be missing.
  • “No, make it required” is correct.

    Marking a property optional with ? tells TypeScript it may be missing. If the business rule says every customer has one, making it required means the checker stops any code creating a customer without it.

    • Types match the rules: required in real life means required in the type.
    • Optional is for things that really can be absent, like a second address line.

📖 Revise: Lesson 2: Optional and readonly properties

Question ID module-28-q3 · Report a mistake in this question
4. Can an interface describe a union like "S" | "M" | "L"?

Why each option is right or wrong

  • “Yes, interfaces can describe any type, including unions” (Incorrect): Interfaces only describe objects. Unions need a type alias.
  • “Yes, but only if all of the values are numbers” (Incorrect): Interfaces can't describe unions of numbers either.
  • “No, unions can only be written in plain JavaScript files” (Incorrect): Unions are a TypeScript feature; plain JavaScript has no types.
  • “No, use a type alias for unions” is correct.

    Interfaces describe the shape of objects: which properties they have. A union of values isn't an object shape, so it needs a type alias: type Size = "S" | "M" | "L".

    • Interface: object shapes, can be extended.
    • Type alias: anything, including unions, and object shapes too.

📖 Revise: Lesson 3: Type aliases and when to use which

Question ID module-28-q4 · Report a mistake in this question
5. Does type Paise = number stop you passing a value in rupees?

Why each option is right or wrong

  • “Yes, TypeScript checks that the number is a whole number of paise” (Incorrect): TypeScript doesn't check units or whole numbers for a plain alias.
  • “Yes, values over 100 are rejected because they're rupees” (Incorrect): TypeScript doesn't know any rules about paise; the alias is just a name.
  • “No, because type aliases are ignored completely by the checker” (Incorrect): Aliases aren't ignored; they're simply the same as the original type.
  • “No, it's just another name for number” is correct.

    A type alias gives a type a new name but doesn't create a new type. Any number fits Paise, including a value in rupees. The name helps people reading the code, but TypeScript won't catch the mix-up.

    • Still useful: it documents the unit.
    • Stronger option: "branded" types can make units really distinct, at the cost of extra code.

📖 Revise: Lesson 3: Type aliases and when to use which

Question ID module-28-q5 · Report a mistake in this question
6. In a Payment union, what's the discriminant?

Why each option is right or wrong

  • “The property that appears in only one of the kinds” (Incorrect): A discriminant appears in every kind, with a different value in each.
  • “The first property listed in each type” (Incorrect): Order doesn't matter. What matters is a shared property with distinct literal values.
  • “The property that holds the payment amount in paise” (Incorrect): The amount is usually the same kind of number in every case, so it can't tell kinds apart.
  • “The property with a different literal value for each kind, such as method” is correct.

    In a discriminated union, each kind shares one property whose exact value is different, like method: "card" or method: "upi". Checking that property tells TypeScript which kind you have, so it knows the other properties available.

    • Example: if (p.method === "card") { p.cardLast4 }.
    • Works well with switch: one case per kind.

📖 Revise: Lesson 4: Discriminated unions

Question ID module-28-q6 · Report a mistake in this question
7. An order has paid: boolean and paidAt?: string. What contradictory state can it represent?

Why each option is right or wrong

  • “paid: true with an order total of zero” (Incorrect): That can be legitimate, like a fully discounted order; it's not what this design makes possible.
  • “An order with no paidAt at all” (Incorrect): Unpaid orders are expected to have no paidAt; that's a valid state.
  • “An order with both paid and paidAt set to sensible values” (Incorrect): That's the normal paid state, not a contradictory one.
  • “paid: false with a paidAt date” is correct.

    These two properties are independent, so nothing stops an order saying it isn't paid while also having a payment date (or paid with no date). A union such as { status: "unpaid" } | { status: "paid"; paidAt: string } rules these contradictions out.

    • Principle: design types so contradictory states can't be written.
    • Fewer checks: code no longer needs to guard against contradictions.

📖 Revise: Lesson 5: Designing types for a real app

Question ID module-28-q7 · Report a mistake in this question
8. Why write types before asking AI to write the functions?

Why each option is right or wrong

  • “AI tools can't write TypeScript without an existing interface” (Incorrect): AI can write TypeScript without them, but the result isn't checked against your design.
  • “Types make the AI answer faster and with fewer words” (Incorrect): Speed isn't the point; the benefit is checking the result.
  • “So the AI can skip writing tests for those functions” (Incorrect): Types and tests catch different problems; you still need tests.
  • “They define exactly what data is allowed, so the AI's code is checked against them” is correct.

    Types are a precise description of your data. Given them first, the AI writes code to fit, and when it gets something wrong, the checker points straight at the mistake.

    • Your design, its code: you stay in charge of the data model.
    • Prompt tip: paste the types and say "use these types without changing them".

📖 Revise: Lesson 5: Designing types for a real app

Question ID module-28-q8 · Report a mistake in this question
9. Why write // in paise above a price property?

Why each option is right or wrong

  • “TypeScript reads the comment and checks the unit for you” (Incorrect): Comments are ignored by the checker. They help people, not the compiler.
  • “Comments make the code compile faster” (Incorrect): Comments have no effect on speed.
  • “It's required, or the property won't accept whole numbers” (Incorrect): number accepts whole numbers with or without a comment.
  • “It records the unit, preventing someone treating it as rupees” is correct.

    The type number says nothing about units. A short comment tells every reader, including an AI, that 4999 means ₹49.99, not ₹4999, avoiding a costly 100× mistake.

    • Or name it: pricePaise makes the unit hard to miss.
    • Why paise: whole numbers avoid rounding errors with decimals.

📖 Revise: Lesson 5: Designing types for a real app

Question ID module-28-q9 · Report a mistake in this question
10. A new payment method is added to a discriminated union. Your switch statements end with a default case containing a never exhaustiveness check. How does TypeScript help?

Why each option is right or wrong

  • “It writes the handling code for the new method automatically” (Incorrect): TypeScript reports gaps; you or an AI still write the handling.
  • “It removes the new method until all the code handles it” (Incorrect): The type checker doesn't change your code. It only reports errors.
  • “It doesn't help; once a union is written and in use, its kinds can't be changed safely” (Incorrect): Unions can be changed any time; the checker then shows what's affected.
  • “It reports every one of those switches that doesn't yet handle the new method” is correct.

    The never check in each default case only compiles when every kind has been handled. Add a new kind and each of those switches now fails to compile, giving you a to-do list of every spot to update.

    • The condition matters: a switch without that check (or without a declared return type) gets no warning.
    • Habit: put the never check in every switch over a union where a missed case would cause a bug.

📖 Revise: Lesson 4: Discriminated unions

Question ID module-28-q10 · Report a mistake in this question

ProLearners Assist