← Back to courses

Course

TypeScript

169 lessons across 14 modules

Beginner to advanced, assuming JavaScript fundamentals. Basic types, functions, interfaces, unions and narrowing, generics, classes, migrating existing JavaScript, tsconfig, React and Node.js, utility and conditional types, and the standards a team needs - ending in a full-stack project typed end to end. The road is laid out in full; lessons are being written one at a time.

Course14 modules169 lessonsEach heading below is a module (one topic). Each card under it is a lesson. Start with Module 1.
Solid: ready (0)Dashed: coming soon (169)
Module 1 of 1412 lessonsComing soon

TypeScript Fundamentals

What it adds to JavaScript, and what it costs

Prerequisite: the JavaScript course →

What is TypeScript?

1

JavaScript with a type system that is checked, then erased.

A .ts file and the .js it compiles to, side by side

Lesson 1planned

Why TypeScript?

2

Catching mistakes before they run, and editors that understand your code.

A typo in a property name caught before the page loads

Lesson 2planned

JavaScript vs TypeScript

3

What changes, what does not, and what the runtime never sees.

Why types cannot validate data that arrives over the network

Lesson 3planned

TypeScript Advantages

4

Refactoring, autocomplete, and documentation that cannot go stale.

Renaming a field across forty files with confidence

Lesson 4planned

TypeScript Compiler

5

tsc checks and emits - two jobs, separable.

A build that emits JavaScript despite type errors

Lesson 5planned

Type Checking

6

Structural typing - shape matters, names do not.

Two unrelated interfaces that are interchangeable

Lesson 6planned

Type Inference

7

The idea - the compiler working out types you did not write.

A whole function typed with a single annotation

Lesson 7planned

Installing TypeScript

8

Per project, not global, and pinned in the lockfile.

Two developers seeing different errors from different versions

Lesson 8planned

First TypeScript Program

9

Writing one, breaking it on purpose, and reading the error.

An error message read line by line

Lesson 9planned

Compiling TypeScript

10

tsc, watch mode, noEmit, and where the output goes.

Type-checking without emitting, the way most projects do

Lesson 10planned

TypeScript with Node.js

11

Running TypeScript on the server, compiled or directly.

tsx against tsc against Node type stripping

Lesson 11planned

TypeScript with Vite

12

Vite strips types and does not check them - so something else must.

A dev server running happily over a type error

Lesson 12planned
Module 2 of 1414 lessonsComing soon

Basic Types

The primitives, and the special types around them

String

13

The string type, and the String wrapper you should never use.

string against String, and why one is wrong

Lesson 13planned

Number

14

One number type for integers and floats alike.

Why there is no int, and what that means for ids

Lesson 14planned

Boolean

15

true and false - and truthiness the type system does not track.

A boolean parameter that makes a call site unreadable

Lesson 15planned

Null

16

An intentional absence, and strictNullChecks making it visible.

The same code with the check off and on

Lesson 16planned

Undefined

17

Not set yet - and how it differs from null in practice.

An optional property against one set to undefined

Lesson 17planned

Any

18

Switching the checker off, and how far that spreads.

One any quietly disabling checks three functions away

Lesson 18planned

Unknown

19

Could be anything - so you must check before you use it.

A JSON.parse result that forces you to validate

Lesson 19planned

Never

20

The type with no values, and the exhaustiveness check it enables.

A switch that fails to compile when a case is added

Lesson 20planned

Void

21

A function that returns nothing useful.

A callback typed as void that may return a value

Lesson 21planned

BigInt

22

Integers beyond the safe range, and not mixing them with number.

A database id too large for a number

Lesson 22planned

Symbol

23

Unique values, and unique symbol for typed keys.

A private-by-convention key that cannot collide

Lesson 23planned

Type Inference

24

The rules - widening, contextual typing, and when inference gives up.

let x = "a" becoming string while const x = "a" stays "a"

Lesson 24planned

Type Annotations

25

Where to write types and where to leave them to inference.

Annotating boundaries, not every local variable

Lesson 25planned

Literal Types

26

A type that is exactly one value.

A direction that can only be "up" or "down"

Lesson 26planned
Module 3 of 1411 lessonsComing soon

Functions

Typing what goes in and what comes out

Function Type Annotations

27

Annotating a function as a whole, not just its parts.

A typed function expression assigned to a variable

Lesson 27planned

Parameter Types

28

Why parameters must be annotated when little else must.

An unannotated parameter becoming implicit any

Lesson 28planned

Return Types

29

Inferred or declared - and why exported functions should declare.

A return type that changes silently after a refactor

Lesson 29planned

Optional Parameters

30

The question mark, and the undefined it adds to the type.

An optional parameter forcing a check in the body

Lesson 30planned

Default Parameters

31

Defaults that make a parameter optional and infer its type.

A default removing the need for an annotation

Lesson 31planned

Rest Parameters

32

Typing a variable number of arguments.

A logger accepting any number of messages

Lesson 32planned

Function Types

33

Describing a function as a type you can reuse.

One Handler type shared by twelve callbacks

Lesson 33planned

Arrow Functions

34

Typing arrows, including generic arrows.

An inline arrow that infers everything from context

Lesson 34planned

Callback Functions

35

Typing the functions you hand to someone else.

An array method callback typed with no annotation at all

Lesson 35planned

Higher-Order Functions

36

Functions that take or return functions, typed end to end.

A withRetry wrapper that keeps the original signature

Lesson 36planned

Function Overloads

37

Several signatures for one implementation - and when a union is simpler.

A parse function whose return type follows its input

Lesson 37planned
Module 4 of 1410 lessonsComing soon

Objects, Interfaces and Type Aliases

Describing the shape of your data

Object Type Annotations

38

Inline object types, and when to give them a name.

An inline type repeated three times, then named once

Lesson 38planned

Interfaces

39

Naming a shape so it can be reused and extended.

A User interface used across a whole app

Lesson 39planned

Optional Properties

40

Properties that may be missing, and handling that honestly.

An optional email that every consumer must check

Lesson 40planned

Readonly Properties

41

Fields that cannot be reassigned - at the type level only.

A readonly id that the runtime still lets you change

Lesson 41planned

Interface Methods

42

Method syntax against property syntax, and the variance difference.

Two ways to write the same method, checked differently

Lesson 42planned

Extending Interfaces

43

Building one interface from another.

An AdminUser that is a User with permissions

Lesson 43planned

Type Aliases

44

Naming any type, not just object shapes.

A union, a tuple, and a function type, each named

Lesson 44planned

Interface vs Type

45

The real differences, and a rule you can follow without thinking.

Declaration merging - the one thing only interfaces do

Lesson 45planned

Nested Objects

46

Deep shapes, and splitting them into named parts.

A user with an address with coordinates

Lesson 46planned

Index Signatures

47

Objects used as dictionaries, and noUncheckedIndexedAccess.

A lookup that should have returned undefined in its type

Lesson 47planned
Module 5 of 1410 lessonsComing soon

Arrays, Tuples and Enums

Collections, fixed positions, and named constants

Typed Arrays

48

Arrays whose elements all share a type.

A list of users that cannot accept a string

Lesson 48planned

Array Type Syntax

49

T[] against Array<T>, and when each reads better.

A union array that needs its brackets

Lesson 49planned

Readonly Arrays

50

Arrays that cannot be mutated through this reference.

A function that promises not to touch its input

Lesson 50planned

Tuples

51

Fixed length, a type per position.

A [latitude, longitude] pair

Lesson 51planned

Named Tuples

52

Labels on positions, for readability and editor hints.

A tuple that documents itself in the tooltip

Lesson 52planned

Optional Tuple Elements

53

Trailing positions that may be absent.

An RGB tuple with an optional alpha

Lesson 53planned

Enums

54

Named constants - and the fact that they emit runtime code.

An enum and the JavaScript object it becomes

Lesson 54planned

Numeric Enums

55

Auto-incrementing values, and the reverse mapping.

A numeric enum accepting a number it never defined

Lesson 55planned

String Enums

56

Readable values in logs and payloads.

A status that means something in a database row

Lesson 56planned

Enum Alternatives

57

Union types and as const objects - usually the better choice.

The same enum rewritten with no runtime cost

Lesson 57planned
Module 6 of 1411 lessonsComing soon

Union, Intersection and Advanced Types

Combining types, and narrowing them back down

Union Types

58

A value that is one of several types.

An id that may be a string or a number

Lesson 58planned

Intersection Types

59

A value that is all of several types at once.

A timestamped entity built from two types

Lesson 59planned

Literal Types

60

Literal unions as the foundation that narrowing is built on.

A status union the compiler can reason about case by case

Lesson 60planned

Type Narrowing

61

The compiler tracking what a value must be after a check.

A union shrinking inside an if block

Lesson 61planned

typeof

62

Narrowing primitives with a runtime check.

Handling a string or number id

Lesson 62planned

instanceof

63

Narrowing class instances.

Telling a ValidationError from any other Error

Lesson 63planned

in

64

Narrowing by the presence of a property.

Separating a Cat from a Dog by what they have

Lesson 64planned

Discriminated Unions

65

A shared tag field that makes every case explicit.

loading, success, and error states in one type

Lesson 65planned

Type Guards

66

Checks the compiler understands and trusts.

A filter that narrows the array it returns

Lesson 66planned

Custom Type Guards

67

Writing value is Type, and the lie it lets you tell.

A guard that is wrong and a compiler that believes it

Lesson 67planned

Nullable Types

68

Handling null and undefined without drowning in checks.

Optional chaining and ?? narrowing as they go

Lesson 68planned
Module 7 of 1411 lessonsComing soon

Generics

Writing something once that keeps its caller types

What are Generics?

69

Type parameters - a function over types, not just values.

An identity function that keeps what it was given

Lesson 69planned

Generic Functions

70

Declaring and inferring type parameters.

getFirst returning the element type, not unknown

Lesson 70planned

Generic Interfaces

71

Interfaces parameterised by the type they carry.

An ApiResponse<T> for every endpoint

Lesson 71planned

Generic Types

72

Type aliases with parameters.

A Result<T, E> used for every fallible call

Lesson 72planned

Generic Classes

73

Classes whose members depend on a type parameter.

A typed Cache<K, V>

Lesson 73planned

Multiple Type Parameters

74

Several parameters, and how they relate.

A map function from T to U

Lesson 74planned

Generic Constraints

75

Requiring a type parameter to have certain capabilities.

A function that needs its input to have an id

Lesson 75planned

extends

76

The constraint keyword, and keyof inside it.

A getProperty that only accepts real keys

Lesson 76planned

Default Generic Types

77

Type parameters that fall back when not supplied.

An event emitter that defaults to string events

Lesson 77planned

Generic Utility Functions

78

Small reusable helpers, typed precisely.

groupBy returning a correctly keyed record

Lesson 78planned

Generic React Components

79

Generics applied to a component, so its props follow its data.

A List<T> whose renderItem receives a T

Lesson 79planned
Module 8 of 1414 lessonsComing soon

Classes and OOP

Classes, modifiers, and inheritance, with types

Classes

80

Class syntax with types, and fields declared up front.

A class that states its shape before its constructor

Lesson 80planned

Constructors

81

Typed constructor parameters, and definite assignment.

A field the compiler says is never initialised

Lesson 81planned

Properties

82

Declared fields, initialisers, and strictPropertyInitialization.

The ! that silences a real bug

Lesson 82planned

Methods

83

Typed methods, and this inside them.

A method that loses this when passed as a callback

Lesson 83planned

Access Modifiers

84

Controlling visibility - at compile time only.

A private field still visible in the compiled output

Lesson 84planned

public

85

The default, and when to write it anyway.

Parameter properties that need a modifier to exist

Lesson 85planned

private

86

TypeScript private against JavaScript #private.

Which one survives a cast and which one does not

Lesson 86planned

protected

87

Visible to subclasses, hidden from everyone else.

A base class hook meant for overriding

Lesson 87planned

readonly

88

Properties set once, in the constructor.

An id that cannot be reassigned after creation

Lesson 88planned

Inheritance

89

extends, super, and override - and preferring composition.

A hierarchy flattened into composed parts

Lesson 89planned

Abstract Classes

90

Base classes that cannot be instantiated, with required members.

A Repository with abstract find and save

Lesson 90planned

Interfaces with Classes

91

implements - a contract the class must satisfy.

Two storage classes behind one interface

Lesson 91planned

Static Members

92

Members on the class itself, not on instances.

A static factory method

Lesson 92planned

Getters and Setters

93

Accessors with types, and validation on assignment.

A setter rejecting a negative price

Lesson 93planned
Module 9 of 1410 lessonsComing soon

TypeScript with JavaScript

Adopting TypeScript in a codebase that already exists

Migrating JavaScript to TypeScript

94

Why a big-bang rewrite fails, and what works instead.

A migration planned one directory at a time

Lesson 94planned

.js vs .ts

95

Mixing both in one project while you move.

A TypeScript file importing a JavaScript one

Lesson 95planned

allowJs

96

Letting the compiler include JavaScript files at all.

The first config change in any migration

Lesson 96planned

checkJs

97

Type-checking JavaScript without renaming a single file.

Errors appearing in plain .js files

Lesson 97planned

JSDoc Types

98

Types written as comments, fully checked.

A typed JavaScript file with no build step

Lesson 98planned

Gradual Migration

99

Loose settings first, tightening one flag at a time.

A migration tracked by error count going down

Lesson 99planned

any Problems

100

Escaping any during a migration without letting it spread.

Counting the anys, and making the number go down

Lesson 100planned

unknown vs any

101

Replacing any with unknown as the safe temporary type.

A migrated function that now forces a check

Lesson 101planned

Handling Legacy JavaScript

102

Declaration files for code you cannot change.

A .d.ts for an untyped internal library

Lesson 102planned

TypeScript Migration Strategy

103

The full plan - order, tooling, and knowing when you are done.

A migration playbook a team can follow

Lesson 103planned
Module 10 of 1414 lessonsComing soon

Modules and Configuration

Imports that erase cleanly, and tsconfig flag by flag

ES Modules

104

How TypeScript resolves modules, and moduleResolution.

An import that works in the editor and fails at runtime

Lesson 104planned

Import

105

Importing values and types, and the extension question.

Why a .ts file imports "./user.js"

Lesson 105planned

Export

106

Exporting values and types from one module.

A barrel file, and what it costs

Lesson 106planned

Default Export

107

Default against named exports, from a types perspective.

A default export that renames freely and breaks search

Lesson 107planned

Type-only Imports

108

import type - guaranteed to erase, never to execute.

A circular import broken by making it type-only

Lesson 108planned

Type-only Exports

109

Re-exporting types without dragging values along.

verbatimModuleSyntax flagging a mixed export

Lesson 109planned

tsconfig.json

110

The project file - what it includes and what it controls.

Reading a real tsconfig and knowing the project

Lesson 110planned

target

111

Which JavaScript version is emitted, and what gets downlevelled.

The same async code at ES5 and at ES2022

Lesson 111planned

module

112

Which module system is emitted.

A package that must ship ESM and CommonJS

Lesson 112planned

strict

113

What the flag switches on - one flag, eight checks.

Listing every check strict enables

Lesson 113planned

noImplicitAny

114

Refusing to guess any when it cannot infer.

Every unannotated parameter surfacing at once

Lesson 114planned

strictNullChecks

115

Making null and undefined their own types.

The flag that finds the most real bugs

Lesson 115planned

paths

116

Import aliases - and why the runtime also needs to know.

An @/ alias that compiles and then fails to resolve

Lesson 116planned

Project References

117

Splitting one large project into incrementally built parts.

A monorepo that type-checks in seconds instead of minutes

Lesson 117planned
Module 11 of 1415 lessonsComing soon

TypeScript with React and Node.js

Typing both ends of a real application

The React course →

Typing React Props

118

Props interfaces, children, and defaults that type correctly.

A Button whose variant cannot be misspelled

Lesson 118planned

Typing State

119

useState inference, and the cases that need an annotation.

State that starts as null and becomes a user

Lesson 119planned

Typing Events

120

The React event types, and finding the right one quickly.

ChangeEvent, MouseEvent, and FormEvent in one form

Lesson 120planned

Typing Forms

121

One type for the form shape, driving state and handlers.

A field name that cannot be typed wrong

Lesson 121planned

Typing useRef

122

DOM refs against value refs, and the null you must handle.

Focusing an input without a non-null assertion

Lesson 122planned

Typing useReducer

123

A discriminated union of actions, checked exhaustively.

Adding an action and letting the compiler find every gap

Lesson 123planned

Typing Custom Hooks

124

Hooks that return tuples or objects with precise types.

A useToggle whose tuple stays a tuple

Lesson 124planned

Generic Components

125

The React-specific typing that makes a generic component pleasant.

A Table whose column keys come from its row type

Lesson 125planned

API Response Types

126

Types for data you did not produce, validated at the boundary.

A cast that lies against a schema that checks

Lesson 126planned

TypeScript with Express

127

A typed Express server, and where the types are weak.

A handler whose request body is any by default

Lesson 127planned

Request Types

128

Typing params, query, and body - and validating them.

A route whose params type matches its path

Lesson 128planned

Response Types

129

Constraining what a handler is allowed to send back.

A response that cannot leak a password field

Lesson 129planned

Middleware Types

130

Extending the request with what middleware adds.

req.user typed after the auth middleware runs

Lesson 130planned

Service Layer Types

131

Types at the seam between routes and business logic.

A service that knows nothing about Express

Lesson 131planned

Database Types

132

Row types, and generating them rather than writing them.

Types generated from the schema, never drifting from it

Lesson 132planned
Module 12 of 1417 lessonsComing soon

Advanced TypeScript

Utility types, and computing types from other types

Utility Types

133

The built-in toolkit for deriving types - an overview.

One User type producing five related types

Lesson 133planned

Partial

134

Every property optional.

An update payload derived from the full type

Lesson 134planned

Required

135

Every property required.

A config type after defaults have been applied

Lesson 135planned

Readonly

136

Every property read-only - one level deep.

A frozen settings object

Lesson 136planned

Pick

137

Keeping a subset of properties.

A UserPreview holding only id and name

Lesson 137planned

Omit

138

Dropping properties - and the typo it will not catch.

A public user without its password hash

Lesson 138planned

Record

139

An object type from a key type and a value type.

A lookup keyed by a status union, with every key required

Lesson 139planned

Exclude

140

Removing members from a union.

Every status except "deleted"

Lesson 140planned

Extract

141

Keeping only the union members that match.

The events that carry a payload

Lesson 141planned

NonNullable

142

Removing null and undefined from a type.

A value after it has been validated

Lesson 142planned

ReturnType

143

The type a function returns, without restating it.

A type derived from a factory function

Lesson 143planned

Parameters

144

A function parameter list, as a tuple.

A wrapper forwarding exactly the same arguments

Lesson 144planned

Awaited

145

Unwrapping a promise, however deeply nested.

The resolved type of an async function

Lesson 145planned

Conditional Types

146

Types that choose between branches, and distribution over unions.

A type that is a string array for strings and a number otherwise

Lesson 146planned

Mapped Types

147

Transforming every property of a type.

Building Partial yourself to see how it works

Lesson 147planned

Template Literal Types

148

String types built from other string types.

Event names like "onClick" derived from "click"

Lesson 148planned

infer

149

Extracting a type from inside another in a conditional type.

Writing your own ReturnType

Lesson 149planned
Module 13 of 1412 lessonsComing soon

TypeScript Best Practices

Standards for a codebase more than one person works in

Avoiding Excessive any

150

any as a review standard - where it is acceptable and where it is not.

A lint rule that makes each any a deliberate choice

Lesson 150planned

unknown vs any

151

unknown as the default for anything untrusted.

A team rule applied to every external input

Lesson 151planned

Strict Mode

152

Turning strict on in a codebase written without it.

Enabling one check at a time until strict is on

Lesson 152planned

Type Naming Conventions

153

Names that say what a type is, with no Hungarian prefixes.

Why IUser and UserType both read badly

Lesson 153planned

Reusable Types

154

Deriving rather than duplicating.

Three hand-written types replaced by one and two utilities

Lesson 154planned

Domain Types

155

Types that model the business, not the database.

Branded ids that cannot be mixed up

Lesson 155planned

API Types

156

Sharing types between client and server, and the risk in that.

One contract package used by both ends

Lesson 156planned

DTO Types

157

Transfer shapes kept apart from domain shapes.

A DTO mapped to a domain object at the boundary

Lesson 157planned

Type Organization

158

Where types live - colocated or shared, and the rule for choosing.

A types folder that became a dumping ground

Lesson 158planned

Type-safe Error Handling

159

catch gives you unknown - and Result types as an alternative.

A function whose errors appear in its signature

Lesson 159planned

Type-safe Configuration

160

Validating environment variables once, at startup.

A missing variable failing at boot rather than at 2am

Lesson 160planned

TypeScript Code Review Guidelines

161

What to look for in a pull request, as a checklist.

Reviewing a real diff against the list

Lesson 161planned
Module 14 of 148 lessonsComing soon

TypeScript Project

A full-stack application, typed end to end

Project Setup and Architecture

162

React, Express, and PostgreSQL in one strict TypeScript repo.

The folder structure and tsconfig agreed before any feature

Lesson 162planned

Shared Types and DTOs

163

The contract between client and server, defined once.

A change to the API breaking the build on both sides

Lesson 163planned

Authentication

164

Typed tokens, a typed request user, and protected routes.

req.user available and typed in every handler

Lesson 164planned

Users, Roles, and Permissions

165

Domain types, discriminated roles, and type guards on access.

A permission check the compiler can see

Lesson 165planned

CRUD and API Integration

166

Generic service functions and typed endpoints end to end.

One generic repository serving three resources

Lesson 166planned

Validation

167

Runtime validation that produces static types.

A schema that is also the TypeScript type

Lesson 167planned

Error Handling

168

Typed errors from database to UI.

A 409 conflict surfacing as a specific message in a form

Lesson 168planned

Testing and Final Review

169

Tests for the parts types cannot prove, and a strict-mode audit.

The finished app with zero any, reviewed against the plan

Lesson 169planned