Skip to content

Module Recap

Module 06 completed the TypeScript Foundations concept track. You now have the full toolkit: a type system that does not just describe values but actively refines them as your code branches and checks. Here is what to carry forward.

typeof guards — narrow primitive types with typeof value === 'string'. Caught errors are unknown in strict TypeScript — narrow with instanceof Error before accessing .message.

instanceof guards — narrow class instances to their specific type inside the branch. The primary tool for error handling in catch blocks.

The in operator — check whether a property exists on an object and narrow the union accordingly. The right tool when types do not share a discriminant, and for validating unknown data from external sources.

Discriminated unions — a shared literal property (the discriminant) tells TypeScript exactly which union member you are working with. switch on the discriminant enables exhaustive handling. Invalid states become unrepresentable.

Type predicatesvalue is T return types propagate narrowing through function boundaries. Correct for encapsulated validation logic, Array.filter with narrowed output, and any reusable check on unknown data.

unknown, any, and neverunknown forces narrowing before use (safe uncertainty). any disables checking (escape hatch, use sparingly). never is the bottom type — values that cannot exist, and the key to exhaustive switch checking via assertNever.

LocationTechniquePurpose
Every catch block in main.tsinstanceof ErrorAccess .message safely on an unknown error
loadHighScore in quiz.tsType predicate isHighScoreValidate JSON.parse output before casting to HighScore
fetchQuestions in api.ts=== ResponseCode.SuccessDiscriminate on the numeric API response code
buildUrl in api.tsTruthiness / typeofOnly append difficulty param when it is not undefined
render function (if using QuizState)switch on statusRoute to the correct screen for each quiz state
assertNever in renderneverCatch unhandled QuizState members at compile time
// typeof — primitives
if (typeof err === 'string') { /* err is string */ }
// instanceof — class instances and errors
if (err instanceof Error) { /* err is Error */ }
// in — property existence
if ('score' in value) { /* value has score property */ }
// Discriminated union switch
switch (state.status) {
case 'active': /* state is { status: 'active'; question: ...; } */ break;
}
// Type predicate
function isHighScore(v: unknown): v is HighScore { /* ... */ }
// unknown — safe entry for external data
const parsed: unknown = JSON.parse(raw);
// never — exhaustive checking
default: assertNever(state); // compile error if a case is missing
TermWhat it means
NarrowingRefining a broad type to a specific one inside a conditional branch
Type guardA check that causes TypeScript to narrow — typeof, instanceof, in, or a predicate
DiscriminantThe shared property in a discriminated union with a unique literal value per member
Type predicateA function with return type value is T — propagates narrowing through function boundaries
unknownA value whose type is not yet determined — must narrow before use
anyDisables type checking — use only at explicit trust boundaries
neverThe bottom type — no value can have this type; used for exhaustive checking
assertNeverA function that accepts never and throws — makes unhandled union cases compile errors

Module 07 — AceIt Project Build →

Module 07 assembles everything. You will scaffold the project from scratch, write types.ts with all interfaces and type aliases, implement api.ts with the generic fetchJson<T>, build QuizEngine in quiz.ts, wire the DOM in ui.ts, and connect it all in main.ts. Every TypeScript concept from Modules 01–06 appears in the finished app.