← thecodex.expert · The Codex Family of Knowledge

Free · No account · Official sources only

TypeScript — Cradle to Mastery

A complete, structured path through TypeScript — from your first type annotation to type-level programming most JavaScript developers never reach. Every lesson points at reference pages already written and verified on this site. Free, no account, no sign-up.

29 lessons 6 stages ~28 hours of reading 10 projects TypeScript 5.x–6.x · curriculum current as of 2026
Start Lesson 1 → Browse the reference instead

How this course works

1
Follow the stages in orderEach stage assumes the one before it. Stage 3 in particular assumes Stage 2 cold.
2
Read the tab the lesson namesReference pages have Beginner, Intermediate and Expert tabs. Read only what the lesson asks for on a first pass.
3
Run every exampleKeep the playground open in a second tab. Reading code you have not run is how misunderstandings survive.
4
Build after each stageDo not save all ten projects for the end. Pick one up as soon as a stage gives you enough to attempt it.
Casual pace: ~10 weeks at 4 hours a week
Steady pace: ~5 weeks at 8 hours a week
Intensive: ~2 weeks full-time
STAGE 0

Before You Start

TypeScript is not a new language so much as a type system bolted onto one you may already know. These two lessons explain that relationship and get a compiler running.

LESSON 1

What is TypeScript?

Microsoft's typed superset of JavaScript, led by C#'s own architect

TypeScript was created at Microsoft under Anders Hejlsberg — the architect of C# and, before that, Turbo Pascal and Delphi — and it is deliberately a *superset* of JavaScript: every valid JavaScript file is already valid TypeScript. Understanding that framing explains why TypeScript never changes runtime behaviour and why its types vanish entirely when compiled.

📚 🟩 Read the Beginner tab only.
Key focus: Why TypeScript adds no runtime behaviour at all, and what “superset of JavaScript” buys you in practice.
⏱ 30 min
Required Reading
→
What is TypeScript? — The Codex

TypeScript's origin and design goals, the superset relationship with JavaScript, where it is used, and the Go-based compiler rewrite now underway.

LESSON 2

Setting Up TypeScript

Install the compiler, then let tsconfig.json decide everything else

Installing TypeScript is one npm command; the part that actually matters is <code>tsconfig.json</code>, which decides how strictly your code is checked and what JavaScript it compiles down to. This lesson gets both in place so every later lesson can be typed and compiled, not just read.

📚 🟩 Read the Beginner tab only.
Key focus: Getting `tsc` running and a first `tsconfig.json` in place, with strict mode on from day one.
⏱ 30 min
Required Reading
→
Setting Up TypeScript — The Codex

Installing the compiler, initialising tsconfig.json, running tsc, and editor integration.

STAGE 1

The Type System's Foundations

The annotations and built-in types you will use in nearly every file. Six lessons — resist the urge to annotate everything as you go; Lesson 4 explains why.

LESSON 3

Basic Types

string, number, boolean — and the two types most languages don't have

TypeScript's primitives map straight onto JavaScript's, but two of its types are unusual: <code>unknown</code> (a value whose type you must narrow before using) and <code>never</code> (a value that can never exist, used for exhaustiveness checks). Both become important later, so meet them now.

📚 🟩 Beginner → ⚡ Intermediate.
Key focus: The difference between `any`, `unknown` and `never`, and why `unknown` is almost always the better choice over `any`.
⏱ 1 hours
Required Reading
→
Basic Types — The Codex

Primitive types, arrays, objects, any vs unknown, never, void, and null/undefined.

LESSON 4

Type Inference

TypeScript figures out most types on its own — annotations are the exception

Beginners over-annotate. TypeScript infers the type of nearly every variable, return value and callback parameter from context, and the inferred type is often *more* precise than what you would write by hand. Knowing where inference works is what keeps TypeScript code readable instead of noisy.

📚 🟩 Beginner → ⚡ Intermediate.
Key focus: Where to let inference do the work, and the few places an explicit annotation genuinely helps.
⏱ 45 min
Required Reading
→
Type Inference — The Codex

How inference works for variables, return types, and contextual typing of callbacks; plus where annotations are still worth writing.

LESSON 5

Functions

Typed parameters, optional and default values, and overloads

Function signatures are where types pay off most immediately — a wrong argument is caught as you type rather than at runtime. This lesson also covers overloads: one function name with several valid signatures, which is common in library code you will read long before you write it.

📚 🟩 Beginner → ⚡ Intermediate.
Key focus: Optional vs default parameters, and when an overload is clearer than a union parameter type.
⏱ 1 hours
Required Reading
→
Functions — The Codex

Parameter and return type annotations, optional and default parameters, rest parameters, and function overloads.

LESSON 6

Tuples

Fixed-length arrays with a type per position

A tuple is an array whose length and per-position types are both fixed — <code>[string, number]</code> rather than <code>(string | number)[]</code>. React's <code>useState</code> returns one, which is why destructuring it gives you correctly-typed values instead of a union.

📚 ⚡ Intermediate.
Key focus: Why a tuple's per-position types are stronger than an array of a union type.
⏱ 45 min
Required Reading
→
Tuples — The Codex

Tuple syntax, named tuple elements, optional and rest elements, and readonly tuples.

LESSON 7

Enums

Named constant groups — and why the handbook now suggests avoiding most of them

Enums are one of the few TypeScript features that emit real JavaScript rather than vanishing at compile time, which is exactly why the official handbook now recommends most new code use union types or <code>as const</code> objects instead. Worth learning because you will meet them in existing code.

📚 ⚡ Intermediate.
Key focus: Why enums break TypeScript's “types disappear at compile time” rule, and what to use instead in new code.
⏱ 45 min
Required Reading
→
Enums — The Codex

Numeric and string enums, const enums, what they compile to, and the union-type/as-const alternatives now preferred.

LESSON 8

Classes

public, private, protected and readonly — access control JavaScript never had

TypeScript adds compile-time access modifiers to JavaScript's classes, plus parameter properties that cut constructor boilerplate considerably. Note the distinction that trips people up: TypeScript's <code>private</code> is checked at compile time only, while JavaScript's own <code>#field</code> syntax is genuinely private at runtime.

📚 ⚡ Intermediate.
Key focus: TypeScript's compile-time `private` vs JavaScript's runtime `#private` — they are not the same thing.
⏱ 1 hours
Required Reading
→
Classes — The Codex

Class syntax with types, access modifiers, readonly, parameter properties, abstract classes, and implementing interfaces.

STAGE 2

Shapes, Unions & Narrowing — TypeScript's Defining Trick

This is the stage that makes TypeScript different from other typed languages: it understands ordinary JavaScript control flow well enough to narrow a union down to one member just from an `if` statement. Six lessons, and the heart of the course.

LESSON 9

Interfaces vs Type Aliases

Two ways to describe an object shape, with one real structural difference

This is among the most-asked TypeScript questions, and the honest answer is that the two are nearly interchangeable for object shapes. The one real difference is declaration merging: interfaces can be reopened and extended by later declarations, type aliases cannot.

📚 🟩 Beginner → ⚡ Intermediate.
Key focus: The one genuine difference (declaration merging), and why the rest is team convention rather than correctness.
⏱ 45 min
Required Reading
→
Interfaces vs Type Aliases — The Codex

interface vs type syntax, extending each, declaration merging, and which to reach for by default.

LESSON 10

Union & Intersection Types

| means “one of these”; & means “all of these at once”

A union type says a value is one of several types; an intersection says it satisfies all of them simultaneously. Unions are how TypeScript models the messy reality of JavaScript values, and they set up everything in the next three lessons — you cannot narrow what you have not first expressed as a union.

📚 🟩 Beginner → ⚡ Intermediate.
Key focus: Reading `A | B` and `A & B` correctly, and why a union's members must be narrowed before use.
⏱ 1 hours
Required Reading
→
Union & Intersection Types — The Codex

Union syntax, intersection syntax, literal-type unions, discriminated unions, and what you can access on an un-narrowed union.

LESSON 11

Types & Interfaces, Tied Together

Structural typing, discriminated unions, and narrowing in one realistic model

This lesson is the synthesis for the shape half of this stage: seeing type aliases, interfaces, unions, discriminated unions and structural typing combined into one realistic data model, rather than each feature in isolation. Structural typing is the key idea to take away — TypeScript cares what a type's shape *is*, not what it is *named*.

📚 ⚡ Intermediate.
Key focus: Structural (“duck”) typing, and why a discriminated union is the single most useful modelling pattern in TypeScript.
⏱ 1 hours
Required Reading
→
Types & Interfaces, Tied Together — The Codex

Types, interfaces, type aliases, union types, discriminated unions, type narrowing, and structural typing together.

LESSON 12

Strict Mode

strict: true is a bundle of flags — strictNullChecks is the one that matters most

<code>strict: true</code> switches on roughly a dozen individual checks at once. The most consequential by far is <code>strictNullChecks</code>, which stops <code>null</code> and <code>undefined</code> from being assignable to every type — turning JavaScript's most common crash into a compile error.

📚 ⚡ Intermediate.
Key focus: What strictNullChecks changes, and why turning strict mode on later is far more painful than starting with it.
⏱ 45 min
Required Reading
→
Strict Mode — The Codex

The individual flags strict bundles, strictNullChecks in detail, noImplicitAny, and migrating an existing codebase onto strict.

LESSON 13

Type Narrowing

A runtime check inside an if statement is enough for TypeScript to know which type you have

This is TypeScript's signature move. Write <code>if (typeof x === "string")</code> and inside that block TypeScript *knows* x is a string — it reads your ordinary JavaScript control flow and narrows the type accordingly. No other mainstream type system tracks plain runtime checks this closely.

📚 🟩 Beginner → ⚡ Intermediate → 🔥 Expert.
Key focus: Control-flow analysis: how typeof, instanceof, truthiness and a discriminant property each narrow a union.
⏱ 1.25 hours
Required Reading
→
Type Narrowing — The Codex

typeof and instanceof narrowing, truthiness checks, the `in` operator, discriminated-union narrowing, and exhaustiveness checking with never.

LESSON 14

Type Guards

Teaching TypeScript to narrow a type you check yourself, with `value is Type`

When a check is too custom for TypeScript to follow on its own, a type guard — a function returning <code>value is Type</code> — tells the compiler what a <code>true</code> result proves. This is the escape hatch that keeps narrowing working at the edges of a real codebase, especially around data arriving from a network.

📚 ⚡ Intermediate → 🔥 Expert.
Key focus: Writing a `value is Type` predicate, and the responsibility that comes with it: the compiler trusts you.
⏱ 1 hours
Required Reading
→
Type Guards — The Codex

User-defined type guards, the `value is Type` return type, assertion functions, and validating external data safely.

STAGE 3

Generics & Type-Level Programming

Where TypeScript goes further than most type systems: types that compute other types. Seven lessons. You will read code like this in every serious library long before you write it yourself, and that alone makes it worth learning.

LESSON 15

Generic Constraints

extends restricts what a type parameter can be

An unconstrained type parameter tells TypeScript almost nothing — you cannot access any property on it, because it could be anything. <code>extends</code> is how you say “this can be any type, as long as it has at least this shape,” which is what makes generic code actually usable.

📚 ⚡ Intermediate.
Key focus: Why an unconstrained `T` lets you do almost nothing, and how `extends` restores useful access.
⏱ 1 hours
Required Reading
→
Generic Constraints — The Codex

Type parameter syntax, extends constraints, keyof constraints, and default type arguments.

LESSON 16

Conditional Types

An if/else for the type system: T extends U ? X : Y

A conditional type branches at the type level, letting one type definition produce different results depending on its input. With <code>infer</code>, it can also extract a type out of another type — the mechanism behind almost every clever type in the standard library.

📚 ⚡ Intermediate → 🔥 Expert.
Key focus: Reading `T extends U ? X : Y`, and what `infer` actually does.
⏱ 1.25 hours
Required Reading
→
Conditional Types — The Codex

Conditional type syntax, nested conditionals, the infer keyword, and distributive conditional types over unions.

LESSON 17

Mapped Types

Derive a new type from every property of an existing one

A mapped type walks over the keys of an existing type and produces a new one, so <code>Readonly&lt;T&gt;</code> or “make every field optional” becomes a single line instead of a duplicated interface that will drift out of sync.

📚 ⚡ Intermediate → 🔥 Expert.
Key focus: The `[K in keyof T]` pattern, plus key remapping and modifier add/remove.
⏱ 1 hours
Required Reading
→
Mapped Types — The Codex

Mapped type syntax, keyof and indexed access, adding/removing readonly and optional modifiers, and key remapping with `as`.

LESSON 18

Template Literal Types

Build string literal types the way you'd build a template string

Template literal types let the type system construct and pattern-match string types — so <code>`on${Capitalize&lt;K&gt;}`</code> can generate <code>onClick</code>, <code>onChange</code> and so on from a set of keys. Unusual among type systems, and the reason some TypeScript APIs feel almost magical.

📚 🔥 Expert.
Key focus: Constructing string types from other types, and the intrinsic string manipulation helpers.
⏱ 1 hours
Required Reading
→
Template Literal Types — The Codex

Template literal type syntax, combining with unions, inference from string patterns, and Uppercase/Lowercase/Capitalize.

LESSON 19

Utility Types

Partial, Pick, Omit, Record — the standard library of the type system

TypeScript ships a set of ready-made mapped and conditional types that cover the transformations you need most: making fields optional, picking or omitting keys, building record types. This lesson also covers <code>satisfies</code> and <code>as const</code>, two modern additions that change how object literals get typed.

📚 🟩 Beginner → ⚡ Intermediate.
Key focus: Which utility type solves which everyday problem, plus what `satisfies` does that a plain annotation does not.
⏱ 1 hours
Required Reading
→
Utility Types — The Codex

Partial, Required, Readonly, Pick, Omit, Record, Exclude/Extract, ReturnType, and the satisfies operator and as const.

LESSON 20

Advanced Generics

Multiple type parameters, defaults, and generic classes

The patterns library authors rely on: several interacting type parameters, sensible defaults so callers rarely specify them, and generic classes that carry their type through every method. This is the point where reading a library's type definitions stops being intimidating.

📚 🔥 Expert.
Key focus: How multiple type parameters constrain each other, and why good defaults make a generic API pleasant to use.
⏱ 1.25 hours
Required Reading
→
Advanced Generics — The Codex

Multiple type parameters, default type arguments, generic classes and interfaces, and generic constraints that reference each other.

LESSON 21

Generics, Tied Together

Type parameters, keyof, conditional types, infer and mapped types in combination

This lesson is the synthesis for this stage: the individual type-level features you just met, combined the way real library code combines them — a generic function whose return type is computed from its input via a conditional type and a mapped type. Read it once the pieces are familiar, not before.

📚 ⚡ Intermediate → 🔥 Expert.
Key focus: Seeing every type-level feature in this stage work together in one realistic, library-shaped example.
⏱ 1.25 hours
Required Reading
→
Generics, Tied Together — The Codex

Type parameters, constraints, keyof, conditional types, infer, mapped types and template literal types in combination.

STAGE 4

Compiler, Config & Modules

TypeScript's output and tooling are configuration-driven to an unusual degree, and most confusing TypeScript problems are really tsconfig problems. Five lessons on the layer around the code.

LESSON 22

The TypeScript Compiler

tsc parses, checks, then erases your types

The single most clarifying fact about TypeScript: <code>tsc</code> type-checks your code and then deletes every type, emitting plain JavaScript. Nothing is checked at runtime. As of 2026 there is also a Go-based rewrite of the compiler that runs roughly ten times faster — a historic change for a project that had always been written in TypeScript itself.

📚 🟩 Beginner → ⚡ Intermediate.
Key focus: Type erasure — why a type can never affect runtime behaviour — and what the Go-based compiler rewrite changes.
⏱ 1 hours
Required Reading
→
The TypeScript Compiler — The Codex

The compile pipeline, type erasure, emitted output, declaration output, and the Go-based compiler rewrite and its performance impact.

LESSON 23

Configuration

Path aliases, config inheritance, and the target/lib distinction

Most “TypeScript is broken” moments are really a <code>tsconfig.json</code> set up wrong. This lesson covers the options that actually matter day to day, including the <code>target</code> vs <code>lib</code> distinction most people conflate: one sets the JavaScript version you emit, the other declares which built-in APIs exist.

📚 ⚡ Intermediate.
Key focus: The target/lib distinction, path aliases, and config inheritance with `extends`.
⏱ 1 hours
Required Reading
→
Configuration — The Codex

tsconfig.json structure, target vs lib vs module, path aliases and baseUrl, project references, and extends for shared config.

LESSON 24

Modules & Namespaces

ES modules are the standard; namespaces are mostly legacy

TypeScript predates the ES module standard, so it invented namespaces to solve the same problem. Today <code>import</code>/<code>export</code> is simply the right answer, and namespaces mainly appear in older code and in declaration files. Knowing which one you are looking at saves real confusion.

📚 ⚡ Intermediate.
Key focus: Why ES modules won, and the type-only import syntax that avoids accidental runtime imports.
⏱ 45 min
Required Reading
→
Modules & Namespaces — The Codex

import/export syntax, default vs named exports, `import type`, module resolution, and namespaces as a legacy feature.

LESSON 25

Declaration Files

`.d.ts` files describe an untyped library's shape, with no implementation

A declaration file is types without code: it tells TypeScript the shape of a JavaScript library that has no types of its own. Understanding them explains where <code>@types/*</code> packages come from and how to type a dependency that ships none.

📚 ⚡ Intermediate → 🔥 Expert.
Key focus: Reading a `.d.ts` file, and what to do when a dependency has no types at all.
⏱ 1 hours
Required Reading
→
Declaration Files — The Codex

declare syntax, .d.ts structure, the @types ecosystem and DefinitelyTyped, ambient declarations, and module augmentation.

LESSON 26

Testing TypeScript

Jest and Vitest run TypeScript directly — and type checking is a separate step

An important distinction: your test runner executing TypeScript is not the same as your types being checked. Most setups transpile tests without type-checking them for speed, which means <code>tsc --noEmit</code> belongs in your pipeline as its own step alongside the test run.

📚 ⚡ Intermediate.
Key focus: Why running tests does not type-check them, and why `tsc --noEmit` belongs in CI separately.
⏱ 1 hours
Required Reading
→
Testing TypeScript — The Codex

Setting up Vitest or Jest with TypeScript, typing mocks, `tsc --noEmit` as a distinct CI step, and testing types themselves.

STAGE 5

Applied TypeScript

Three lessons on TypeScript where it is actually used: asynchronous code, React components, and decorators — the feature whose syntax changed entirely in 2023.

LESSON 27

Typing Async Code

Promise<T> types what an async function eventually resolves to

An <code>async</code> function always returns a <code>Promise&lt;T&gt;</code>, and <code>await</code> simply unwraps it back to <code>T</code>. The genuinely important part is typing failure: a rejected promise is typed as <code>unknown</code> in a catch block under modern settings, which forces you to narrow before assuming you caught an <code>Error</code>.

📚 🟩 Beginner → ⚡ Intermediate.
Key focus: How Promise<T> and await relate, and why a caught error is `unknown` rather than `Error`.
⏱ 1 hours
Required Reading
→
Typing Async Code — The Codex

Promise<T>, async/await typing, typing rejected promises and catch clauses, Awaited<T>, and typing concurrent calls.

LESSON 28

TypeScript with React

Typed props, typed hooks, and the .tsx extension

React is where most people meet TypeScript in earnest. Typed props turn a component's contract into something the compiler enforces, and typed hooks — especially <code>useState</code>, which returns a tuple — are where the tuple lesson from Stage 1 pays off directly.

📚 ⚡ Intermediate.
Key focus: Typing props and hooks correctly, and why `.tsx` exists as a separate extension.
⏱ 1.25 hours
Required Reading
→
TypeScript with React — The Codex

The .tsx extension, typing props and children, typing useState/useRef/useReducer, event handler types, and generic components.

LESSON 29

Decorators

The standard syntax replaced TypeScript's experimental one in 2023 — they are not compatible

Decorators are now a real JavaScript standard, and TypeScript's modern implementation follows it. Critically, the older <code>experimentalDecorators</code> version is a different, incompatible design — so a tutorial or library written for one will not work under the other. Knowing which you are looking at is the whole battle.

📚 🔥 Expert.
Key focus: Telling standard decorators apart from the legacy experimental ones, and why mixing them breaks.
⏱ 1 hours
Required Reading
→
Decorators — The Codex

Standard decorator syntax and semantics, the legacy experimentalDecorators flag and how it differs, and common decorator use cases.

STAGE 6

Concepts That Cross Languages

These pages explain ideas that are not specific to TypeScript — they apply to every language you will ever learn. Read them once and the next language costs you far less effort. They pair well with the lessons above rather than replacing them.

STAGE 7

Build Real Things — 10 Projects

Reading is not enough. These 10 projects — five basic, five medium — are chosen because each one exercises something specific you learned above, and because they are genuinely idiomatic TypeScript rather than generic exercises. Each link below opens the project brief; the TypeScript implementation walkthrough is in progress.

BASIC — 5 PROJECTS
→
Number Guessing Game

Typed input parsing, loops, and narrowing a string to a number.

→
Temperature Converter

Typed functions, union types for the conversion direction, and exhaustiveness checking.

→
Word Counter

Reading files with typed Node APIs, and Record<string, number> for counting.

→
To-Do List (CLI)

Interfaces for the task shape, and typing JSON parsed from disk as unknown first.

→
Password Generator

Typed configuration objects, as const character pools, and tuple returns.

MEDIUM — 5 PROJECTS
→
Web Scraper

fetch with typed responses, and validating external data before trusting its type.

→
REST API

Typed request/response handlers, discriminated-union error results, and shared types across the API boundary.

→
CLI Task Manager

Discriminated unions for subcommands, and exhaustiveness checking so a missing case is a compile error.

→
URL Shortener

A typed in-memory store with Map<string, string>, and branded types for codes vs URLs.

→
Log Analyser

Typed parsing of semi-structured lines, and generics for a reusable top-N counter.

STAGE 8

Practice & Experimentation

Ongoing, not a final step. Use these throughout the course — try every snippet you read, and run anything you are unsure about rather than assuming.

Resources
→
TypeScript Playground

Run TypeScript code without installing anything, via the official TypeScript Playground.

→
TypeScript Snippets

Copy-ready idiomatic patterns to keep beside you while you build.

→
TypeScript Reference Hub

All 29 topic pages in one index, for looking things up later.