Step 1 • Setup
Why TypeScript and Setup beginner Understand the value proposition of TypeScript — catch bugs at compile time instead of runtime, get IDE autocomplete and refactoring tools, make code self-documenting with types. Install TypeScript, configure tsconfig.json (target, module, lib, strict, outDir, rootDir), use ts-node or tsx for running TypeScript directly, and understand the compile-only nature (TypeScript erases all types at runtime).
Build TypeScript 3h Step 2 • Foundations
Basic Types and Type Annotations beginner Annotate JavaScript with TypeScript's type system — primitive types (string, number, boolean, null, undefined, bigint, symbol), arrays (string[] or Array<string>), tuples ([string, number]), object types (inline vs named), the difference between null and undefined, any (avoid it — disables type checking), and unknown (safe alternative to any that requires narrowing before use).
Language TypeScript 5h Step 3 • Foundations
Type Inference and the Compiler beginner Understand how TypeScript infers types without annotations — contextual typing, widening (let x = 'hello' → string), const narrowing (const x = 'hello' → 'hello' literal), and when inference is enough vs when you must annotate. Learn to use TypeScript's language server to inspect inferred types (hover in VS Code), and how the compiler assigns types to function return values.
Language TypeScript 4h Step 4 • Foundations
Union, Intersection, and Literal Types beginner Model values that can be one of several types — union types (A | B, the OR of types), intersection types (A & B, combining shapes), literal types (the exact value 'success' | 'error' instead of string), const assertions (as const to narrow to literals), and template literal types (``${string}-id`` type patterns). Understand when to use unions vs polymorphism.
Language TypeScript 5h Step 5 • Foundations
Narrowing, Type Guards, and Discriminated Unions beginner Use TypeScript's control flow analysis to narrow types — typeof (primitive narrowing), instanceof, in operator, equality narrowing (=== check), user-defined type guards (function isError(x): x is Error), assertion functions (function assert(x): asserts x), and discriminated unions (a union where each member has a literal discriminant field that makes exhaustive handling possible with switch + never).
Language TypeScript 6h Step 6 • Foundations
Interfaces, Type Aliases, and Object Shapes beginner Define reusable object shapes with interface and type — when to use interface (open for declaration merging, clearer error messages for objects) vs type (for unions, intersections, computed types, anything interface can't express), readonly properties, optional properties (?), index signatures ([key: string]: T), and satisfies operator (check type without widening).
Language TypeScript 5h Step 7 • Generics
Generics intermediate Write reusable, type-safe functions and classes with generics — type parameters (function identity<T>(x: T): T), generic constraints (T extends string), multiple type parameters, default type parameters, and the common pattern of a generic function that infers its type parameter from arguments. Understand when generics are necessary vs when they overcomplicate code.
Language TypeScript 8h Step 8 • Generics
Built-in Utility Types intermediate Use TypeScript's built-in utility types to derive new types instead of duplicating — Partial<T> (all optional), Required<T> (all required), Readonly<T>, Pick<T, K> (subset of keys), Omit<T, K> (exclude keys), Record<K, V> (key-value map), Exclude<T, U> (remove from union), Extract<T, U> (keep from union), NonNullable<T>, ReturnType<F>, Parameters<F>, InstanceType<C>, and Awaited<T>.
Language TypeScript 6h Step 9 • Advanced Types
Mapped Types and Conditional Types intermediate Create new types by transforming existing ones — mapped types (iterate over keys: { [K in keyof T]: ... }), adding/removing modifiers (readonly, ?), key remapping with as, conditional types (T extends U ? X : Y), the infer keyword to extract types from conditional types, distributive conditional types, and recursive types (e.g., DeepPartial<T>, DeepReadonly<T>).
Language TypeScript 8h Step 10 • Tooling
Modules, Declaration Files, and tsconfig intermediate Configure TypeScript projects correctly — module systems (ESNext vs CommonJS, moduleResolution: bundler/NodeNext), path aliases (paths + baseUrl), strict compiler options (strict, noImplicitAny, strictNullChecks, noUncheckedIndexedAccess), project references for monorepos, declaration files (.d.ts — what they are, how they're consumed), and DefinitelyTyped (@types/* packages).
Backend TypeScript 6h Step 11 • Tooling
Runtime Validation with Zod intermediate Bridge the gap between TypeScript's compile-time types and runtime reality — TypeScript types disappear at runtime, so any external input (API responses, user input, environment variables, database results) needs runtime validation. Use Zod to define schemas that both validate at runtime AND infer static TypeScript types (z.infer<typeof schema>). Understand the schema-first approach to type safety.
Backend TypeScript 6h Step 12 • Tooling
Typed Errors and Async Code intermediate Handle errors correctly in TypeScript — why catch(e) gives unknown in strict mode (use unknown, not any), custom error classes with discriminated union types, the Result<T, E> pattern (return errors as values instead of throwing), typed async functions (Promise<T> and async return type inference), and avoiding the trap of unhandled promise rejections.
Backend TypeScript 6h Step 13 • Quality
typescript-eslint and Code Quality intermediate Enforce TypeScript-aware linting rules with typescript-eslint — type-aware lint rules (no-floating-promises, no-misused-promises, strict-boolean-expressions, no-explicit-any), configure it in flat config format, integrate Prettier for formatting, and set up the rules in CI so they fail the build on violations. Understand which rules prevent real bugs vs which are stylistic.
Testing TypeScript 5h Step 14 • Quality
Testing TypeScript Code intermediate Write type-safe tests — use Vitest (native TypeScript + ESM support), write type-level tests with tsd or expectTypeOf to verify your types behave correctly, create typed factories for test data (never use as any in tests), and mock modules with vi.mock while keeping mock types accurate. Understand how to test generic functions and discriminated unions exhaustively.
Testing TypeScript 7h Step 15 • Advanced
Declaration Files and Library Authoring advanced Ship TypeScript types as part of a library — .d.ts files (what they are, how the compiler generates them with declaration: true), the exports map in package.json for dual ESM/CJS packages with types, writing manual declaration files for JavaScript libraries that lack @types, contributing to DefinitelyTyped, and designing a public API that's pleasant to use from TypeScript.
Backend TypeScript 7h Step 16 • Advanced
Advanced Patterns and Type Design advanced Apply advanced TypeScript techniques — branded types (prevent type confusion: UserId vs TeamId, both strings), opaque types via declaration merging, const assertions for readonly object hierarchies, satisfies for checked object literals, variance (covariance vs contravariance in function types), and how to design types that make invalid states unrepresentable. Know when type complexity hurts more than it helps.
Language TypeScript 8h Step 17 • Ship It
Production-Safe Type Design and Migration advanced Apply TypeScript pragmatically in production — migrating a JavaScript codebase to TypeScript incrementally (allowJs, checkJs, strict mode gradually), avoiding the anti-patterns that make TypeScript painful (overuse of any, type assertions everywhere, massive type utilities that nobody understands), setting up project references for monorepos, and versioning your types for library consumers.
Hosting TypeScript 7h