Module Recap
Module 03 gave names to the shapes you described inline in Module 02. The result is a types.ts file that the rest of the app imports from — a single source of truth for every data contract in AceIt.
What you learned
Section titled “What you learned”Type aliases — type Name = ... gives any type a name: unions, tuples, function signatures, object shapes, or combinations. Changes to a named type propagate everywhere it is used.
Interfaces — interface Name { ... } declares a named object shape. Interfaces describe the contract between parts of the code. Any object satisfying the declared properties passes the type check — structural typing applies.
Optional properties (?) — a property that may be present or absent. TypeScript widens its type to T | undefined and requires a check before use.
Readonly properties — a property that cannot be reassigned after creation. Applied to value objects like TriviaQuestion to communicate that the data is fixed after normalization.
Extends — interface B extends A inherits A’s properties into B. Multiple parents are allowed. Property conflicts are caught at the declaration site.
Intersection (&) — composes type aliases mechanically. Equivalent to extends for simple shapes, but silent on property conflicts.
interface vs type — use interface for named data models; use type for unions, tuples, function types, and anything interface cannot express.
AceIt’s complete types.ts
Section titled “AceIt’s complete types.ts”After this module, types.ts looks like this:
// ── Type aliases ───────────────────────────────────
export type Difficulty = 'easy' | 'medium' | 'hard';
export type ScreenId = | 'start-screen' | 'loading-screen' | 'question-screen' | 'result-screen';
export type QuizState = | { status: 'idle' } | { status: 'loading' } | { status: 'active'; question: TriviaQuestion; index: number; total: number } | { status: 'done'; score: number; total: number };
// ── API response shapes ────────────────────────────
export interface RawQuestion { type: string; difficulty: string; category: string; question: string; correct_answer: string; incorrect_answers: string[];}
export interface ApiResponse { response_code: number; results: RawQuestion[];}
// ── App data shapes ────────────────────────────────
export interface TriviaQuestion { readonly question: string; readonly category: string; readonly difficulty: Difficulty; readonly correctAnswer: string; readonly allAnswers: string[];}
export interface HighScore { score: number; total: number; date: string;}
// ── Enum ───────────────────────────────────────────
export enum ResponseCode { Success = 0, NoResults = 1, InvalidParam = 2, TokenNotFound = 3, TokenEmpty = 4,}Note: RawQuestion and TriviaQuestion share the fields question, category, and difficulty — you practiced factoring these into a BaseQuestion with extends in Lesson 04. The final project keeps the interfaces flat for simplicity, but the extends pattern is worth knowing for codebases where the shared base grows.
Every other file in AceIt imports from this file. api.ts uses ApiResponse, RawQuestion, TriviaQuestion, Difficulty, and ResponseCode. quiz.ts uses TriviaQuestion and HighScore. ui.ts uses TriviaQuestion, HighScore, and ScreenId. main.ts uses Difficulty.
Key terms
Section titled “Key terms”| Term | What it means |
|---|---|
| Type alias | A named type created with type Name = ... — can describe any type |
| Interface | A named object shape created with interface Name { ... } |
| Optional property | property?: T — may be absent; TypeScript treats it as T | undefined |
| Readonly property | readonly property: T — cannot be reassigned after creation |
| Declaration merging | Two interface declarations with the same name merge into one |
| extends | Interface inheritance — B extends A gives B all of A’s properties |
| Structural typing | Compatibility based on shape — an object fits a type if it has the required properties |
What is next
Section titled “What is next”Module 04 — Functions and Classes →
Module 04 types the functions and classes that drive AceIt’s logic. You will write typed function parameters and return types in depth, type function expressions and callbacks, build the QuizEngine class with typed properties and access modifiers, and see how TypeScript’s readonly modifier applies to class fields.