The Ultimate TypeScript Course

Section 1: Introduction to TypeScript
  1. Welcome to the Course
  2. How to Follow This Course?
  3. How to Remember Everything We Learn?
  4. Prerequisites for Learning TypeScript
  5. What is TypeScript & How does it Work?
  6. History of TypeScript
Section 2: TypeScript Fundamentals and Compiler Configuration
  1. What Are Types?
  2. Compiling TypeScript to JavaScript
  3. Configuring the TypeScript Compiler
  4. Strict Mode in TypeScript
  5. Debugging TypeScript Applications
  6. Including and Excluding Files in TypeScript
  7. Initializing a TypeScript Project Using the Init Command
  8. Statically vs Dynamically Typed Languages
  9. Strongly vs Weakly Typed Languages
  10. Top and Bottom Types in TypeScript
Section 3: Arrays and Tuples in TypeScript
  1. Array Typing in TypeScript
  2. Array Methods in TypeScript
  3. What Are Tuples?
  4. Readonly Arrays and Tuples
Section 4: Type Aliases, Literal Types, and Type Assertions
  1. What Are Type Aliases?
  2. Understanding Literal Types
  3. Template Literal Types
  4. Type Assertions in TypeScript
  5. Non-null Assertion in TypeScript
  6. Definite Assignment Assertion in TypeScript
Section 5: Objects & Functions Typing in Depth
  1. Object Literal Types
  2. Interfaces in TypeScript
  3. Types vs Interfaces
  4. Benchmarking Types and Interfaces
  5. Module Detection in TypeScript
  6. Why Do We Need Declaration Merging?
  7. Object Types from JavaScript
  8. Function Typing in TypeScript
  9. Creating Reusable Function Types
  10. Method Typing in Objects
  11. Optional Parameters in Functions and Methods
  12. Typing Rest Parameters in TypeScript
  13. Structural vs Nominal Typing
Section 6: Demystifying Unions and Intersections Using Set Theory
  1. Introduction to Set Theory
  2. Union and Intersection in Set Theory
  3. Value-Based and Property-Based Sets
  4. Union and Intersection in Property-Based Sets
  5. Types as Sets of JavaScript Values
  6. Union and Intersection in TypeScript
  7. Understanding Object Types in Depth
  8. Union and Intersection of Objects
  9. Union and Intersection with Conflicting Property Types
  10. Union and Intersection of Arrays
  11. The Research Behind Types as Sets: From Intuition to Proof
  12. Installing TypeScript Version 7.0
Section 7: Mastering Generics in TypeScript
  1. Introduction to Generics
  2. Creating Generic Interfaces
  3. Generic Functions in TypeScript
  4. Different Ways to Create Generic Functions
  5. Multiple Parameters in Generics
  6. Practical Use of Generic Functions
  7. Default Params in Generics
  8. Adding Constraints to Generics
  9. Generic Methods in TypeScript
  10. Working with Nested Generics
  11. Recursive Generics in TypeScript
  12. Built-in Generics in TypeScript
  13. Understanding Promise<T> in TypeScript
  14. Function Overloading in TypeScript
  15. Understanding const Modifier in Type Parameters
Section 8: Type-Level Programming in TypeScript
  1. Introduction to Type-Level Programming
  2. Fundamental Unit of Type-Level Programming
  3. Understanding typeof Operator at Type Level
  4. Understanding keyof Operator in TypeScript
  5. What Is Vacuous Truth?
  6. Indexed Access Types in TypeScript
  7. Index Signatures in TypeScript
  8. Mapped Types in TypeScript
  9. Key Remapping in Mapped Types
  10. Property Modifiers in Mapped Types
  11. Conditional Types in TypeScript
  12. Possible Outcomes of Conditional Types
  13. Distributive Conditional Types
  14. Nested Conditionals and Key Removal in Mapped Types
  15. The infer Keyword in Conditional Types
  16. Tuple Pattern Matching with infer Keyword
  17. Type-Level Recursion with Conditional Types
  18. Type-Level Arithmetic Operations
  19. Branded Types in TypeScript
  20. Real-World Use Cases of Type-Level Programming
Section 9: Utility Types in TypeScript
  1. Introduction to Utility Types
  2. Union Utility Types: Exclude, Extract, and NonNullable
  3. Property Modifier Utility Types: Partial, Required, and Readonly
  4. Property Selection Utility Types: Pick and Omit
  5. Object Mapping Utility Types: Record
  6. Function Utility Types: Parameters and ReturnType
  7. String Manipulation Utility Types: Uppercase, Lowercase, Capitalize, and Uncapitalize
  8. Promise Utility Types: Awaited
  9. Inference Control Utility Types: NoInfer
  10. Combining Multiple Utility Types
  11. Creating Custom Utility Types
  12. Exploring Third-Party Utility Libraries
  13. Assignment: TypeScript Type-Challenges
  14. Additional Resources for Practice
Section 10: Type Narrowing & Control Flow Analysis
  1. Introduction to Control Flow Analysis
  2. Type Widening and Type Narrowing in TypeScript
  3. Type Narrowing Techniques and Purpose
  4. Narrowing with typeof Type Guard
  5. Narrowing with instanceof Type Guard
  6. Narrowing with the in Operator Type Guard
  7. Equality Narrowing in TypeScript
  8. Truthiness Narrowing in TypeScript
  9. Assignment-Based Narrowing in TypeScript
  10. Discriminated Union Narrowing in TypeScript
  11. What is a Predicate in Logic and Mathematics?
  12. User-Defined Type Guards with Type Predicates
  13. Assertion Functions and Type Narrowing with asserts Keyword
  14. Exhaustiveness Checking in TypeScript
  15. Type Narrowing in Generic Functions
  16. Narrowing Across Function Boundaries
  17. Control Flow Analysis of Aliased Conditions and Discriminants
  18. The satisfies Operator in TypeScript
Section 11: Understanding Modules in TypeScript
  1. Why Do We Need Modules?
  2. ES Modules vs CommonJS: The Real Difference
  3. Importing and Exporting Values
  4. Mastering Import and Export Patterns
  5. When to Use Default vs Named Exports
  6. Re-Exporting Modules Efficiently
  7. Understanding Type-Only Imports and Exports
  8. How Module Resolution Works in TypeScript
  9. Understanding File Extensions in TypeScript Imports
  10. Configuring Modules with module Compiler Option
  11. Configuring Module Resolution with moduleResolution Compiler Option
  12. Understanding Package Entry Points
  13. Working with Package Exports and Imports
  14. Import Attributes and the with Keyword
  15. Importing JavaScript Files into TypeScript
  16. How Node.js Resolves Modules
  17. Understanding Bare, Relative, and Absolute Imports
  18. Debugging Module Resolution Problems
Section 12: Ambient Declarations and Declaration Files
  1. What Are Ambient Declarations?
  2. Understanding the declare Keyword
  3. Declaring Global Variables
  4. Declaring Global Functions and Objects
  5. Global vs Module Scope in TypeScript
  6. Declaring Modules Using declare module
  7. Understanding Ambient Modules
  8. Wildcard Module Declarations
  9. What Are Declaration Files (.d.ts)?
  10. Why TypeScript Needs Declaration Files
  11. Understanding How TypeScript Finds Types
  12. Exploring Built-in Declaration Files Like lib.es6.d.ts
  13. Writing Declaration Files for JavaScript Libraries
  14. Understanding @types and DefinitelyTyped
  15. Module Augmentation Explained
  16. Global Augmentation Explained
  17. Extending Existing Types Safely
  18. Common Mistakes in Declaration Files
  19. Mental Model of Ambient Declarations and Declaration Files
  20. @ Directives in TypeScript
Section 13: Runtime Type Safety with Zod
  1. Why Runtime Validation Matters
  2. Compile-Time vs Runtime Type Safety
  3. Why JSON.parse() is Not Type-Safe?
  4. Why API Responses are Not Type-Safe?
  5. Introduction to Zod
  6. Creating Your First Schema
  7. Validating Data with parse
  8. Object Schemas
  9. Array Schemas
  10. Nested Schemas
  11. Optional and Nullable Fields
  12. Default Values in Schemas
  13. Union Schemas
  14. Literal Schemas
  15. Validating Strings with Regular Expressions
  16. Custom Validation with refine
  17. Transforming Data During Validation
  18. Understanding Validation Errors
  19. Inferring Types from Schemas
  20. Schema Composition and Reusability
  21. Type-Safe Data Fetching with Zod
  22. Building a Reusable API Client with Zod
  23. Validating API Request Data
  24. Using Zod with Forms
  25. Overview of Valibot, ArkType, and Other Alternatives
Section 14: Building a Type-Safe Schema Validation Library
  1. Designing a Schema Validation Library
  2. Creating Our First String Validator
  3. Creating Number and Boolean Validators
  4. Building a Common Validator Interface
  5. Implementing Data Validation with parse
  6. Building Object Validators
  7. Building Array Validators
  8. Implementing Optional Fields
  9. Adding Custom Validation Rules
  10. Implementing Method Chaining
  11. Inferring Static Types from Validators
  12. Creating an Infer Utility Type
  13. Improving Error Messages
  14. Supporting Nested Validators
  15. Building a Complete User Schema
  16. Testing Our Library
  17. Limitations of Our Implementation
  18. How Production Libraries Work Internally
Section 15: TypeScript and the DOM
  1. Understanding DOM Types in TypeScript
  2. Exploring lib.dom.d.ts and Built-in Browser Types
  3. Using document and window Safely
  4. Querying Elements with querySelector and querySelectorAll
  5. Handling null from DOM Queries
  6. Type Narrowing for DOM Elements using instanceof
  7. Using Type Assertions (as) with DOM Elements
  8. Using Generics with DOM APIs like querySelector<T>
  9. Working with Specific Element Types like HTMLInputElement and HTMLButtonElement
  10. Understanding Event and EventTarget
  11. Typing Event Handlers like MouseEvent and KeyboardEvent
  12. Safely Accessing event.target with Type Guards
  13. Working with Forms and Inputs in TypeScript
  14. Handling DOM Collections like NodeList and HTMLCollection
  15. Understanding Differences Between NodeList and Arrays
  16. Manipulating DOM Elements with Full Type Safety
Section 16: TypeScript in React
  1. Why React Needs TypeScript: Understanding Type Safety in UI Development
  2. Understanding JSX, TSX, and React's Built-in Type Definitions
  3. Typing Function Components: Props, Return Types, and When to Avoid React.FC
  4. Typing Props with type, interface, Optional Props, Default Values, and Readonly Props
  5. Typing children Correctly: ReactNode, ReactElement, JSX.Element, and Function-as-Children
  6. Passing Functions as Props: Typing Callbacks, Event Handlers, and Custom Function Props
  7. Typing React Events: ChangeEvent, MouseEvent, FormEvent, KeyboardEvent, and SyntheticEvent
  8. Typing useState: Inference, Explicit Generics, Objects, Arrays, Union Types, and Nullable State
  9. Modeling UI States with TypeScript: Loading, Success, Error, Empty, and Disabled States
  10. Typing useReducer: State Types, Action Types, Discriminated Unions, and Exhaustiveness Checking
  11. Typing useRef: DOM Refs, Mutable Refs, Null Handling, and Common Ref Mistakes
  12. Typing forwardRef and useImperativeHandle
  13. Typing useEffect, Cleanup Functions, Async Logic, and Dependency Arrays
  14. Typing useMemo and useCallback: Inference, Function Types, and Performance-Related Patterns
  15. Typing Custom Hooks: Parameters, Return Types, Tuples, Objects, Generics, and Reusable Hook APIs
  16. Typing React Context API: Creating Safe Contexts, Provider Props, Custom Context Hooks, and Context with Reducers
  17. Typing Forms in React: Controlled Inputs, Form Events, Field Values, Errors, and Validation Results
  18. Runtime Validation in React: Connecting API Data with TypeScript Using Zod and z.infer
  19. Typing CSS in React: CSSProperties, CSS Modules, Class Names, and Variant-Based Styling
  20. Reusing Native HTML Props: ComponentProps, ComponentPropsWithoutRef, and ComponentPropsWithRef
  21. Creating Reusable Components with Generics: Lists, Tables, Select Components, and Data-Driven UI
  22. Advanced Component Patterns: Render Props, Compound Components, Polymorphic Components, and the as Prop
  23. Type-Safe Routing in React: Route Params, Search Params, Navigation State, and Route Config Objects
  24. Common TypeScript Mistakes in React and How to Refactor Unsafe Components
Section 17: TypeScript in Node.js
  1. Why Backend Code Needs TypeScript: Type Safety at Runtime Boundaries
  2. Understanding Node.js Type Definitions: @types/node, Built-in Modules, and Runtime APIs
  3. Typing Environment Variables and Configuration: process.env, Runtime Validation, and Safe Config Objects
  4. Typing Async Backend Code: Promise, async Functions, Error Cases, and unknown Data
  5. Understanding Express Types: Request, Response, NextFunction, and RequestHandler
  6. Typing Express Requests: req.params, req.query, req.body, Headers, Cookies, and Files
  7. Typing Express Responses: res.json, Status Codes, Success Responses, Error Responses, and Response Helpers
  8. Typing Route Handlers, Controllers, Services, and Repository Layers
  9. Typing Express Middleware: Normal Middleware, Error Middleware, Auth Middleware, and Reusable Middleware
  10. Extending Express Request Safely: Declaration Merging, Auth User, Role, and Session Data
  11. Type-Safe Authentication and Authorization: JWT Payloads, Sessions, Roles, Permissions, and Protected Routes
  12. Runtime Validation in Node.js: Validating Body, Params, Query, Headers, Cookies, and Environment Variables
  13. Using Zod with Node.js: Schemas, z.infer, Validation Middleware, and Error Formatting
  14. Designing Type-Safe API Contracts: Request Types, Response Types, DTOs, and Shared Types
  15. Typing Database Code with Mongoose: Schemas, Models, Documents, Methods, Statics, and Object IDs
  16. Typing Database Code with Prisma: Generated Types, Create Inputs, Update Inputs, Select, Include, and Query Results
  17. Separating Database Types, Domain Types, and API Response Types Safely
  18. Type-Safe Error Handling: Custom Error Classes, Error Codes, Error Responses, and Result Types
  19. Typing External API Calls and Webhooks: Unknown Responses, Runtime Validation, Event Payloads, and Discriminated Unions
  20. Typing File Uploads, Buffers, Streams, and Storage Operations
  21. Typing Background Jobs, Queues, Cron Jobs, and Event Emitters
  22. Using Advanced TypeScript Patterns in Backend Code: Branded Types, Utility Types, Literal Types, and as const
  23. End-to-End Type Safety: Sharing Types Between Frontend and Backend
  24. Introduction to tRPC and When It Is Better Than Traditional REST Type Sharing
  25. Common TypeScript Mistakes in Node.js and Refactoring Unsafe Backend Code
Section 18: Production-Grade TypeScript Setup
  1. Why Most TypeScript Projects Are Misconfigured
  2. Understanding Modern TypeScript Development Workflows
  3. Running TypeScript with tsc
  4. Running TypeScript with ts-node
  5. Running TypeScript with tsx
  6. Native TypeScript Support in Node.js
  7. Development vs Production Workflows
  8. Creating a Reusable Base tsconfig.json
  9. Understanding strict Mode
  10. Making Indexed Access Safer with noUncheckedIndexedAccess
  11. Understanding exactOptionalPropertyTypes
  12. Understanding noImplicitOverride
  13. Useful Compiler Options for Real-World Projects
  14. Understanding Path Aliases in TypeScript
  15. Configuring Path Aliases with baseUrl and paths
  16. Using Path Aliases in Frontend Applications
  17. Using Path Aliases in Node.js Applications
  18. Runtime Challenges of Path Aliases
  19. When Not to Use Path Aliases
  20. Alternatives to Path Aliases
  21. Setting Up ESLint with TypeScript
  22. Setting Up Prettier
  23. Recommended VS Code Settings for TypeScript
  24. Type Checking in CI/CD Pipelines
  25. Building a Production-Ready TypeScript Project
Section 19: Understanding TypeScript Runtime Features
  1. Why Some TypeScript Features Generate Runtime Code
  2. Understanding the erasableSyntaxOnly Option
  3. Compile-Time vs Runtime in TypeScript
  4. What Gets Erased and What Stays After Compilation
  5. Understanding TypeScript Code Generation
  6. Introduction to Enums in TypeScript
  7. Numeric Enums and Their Runtime Behavior
  8. String Enums and Differences from Numeric Enums
  9. Reverse Mapping in Enums Explained
  10. Const Enums and Compile-Time Optimization
  11. Enums vs Union Types (When to Use What)
  12. Enums vs Objects as Alternatives
  13. Why TypeScript Introduced Namespaces
  14. Understanding Namespaces in TypeScript
  15. Namespace Augmentation
  16. Namespaces vs ES Modules
  17. Namespaces and Their Runtime Impact
  18. Node.js Native TypeScript Support Explained
  19. Mental Model of TypeScript Runtime Features
Section 20: Object Oriented Programming in TypeScript
  1. How Interfaces Bring Structure to Your Code
  2. Interface Inheritance and Reuse Done Right
  3. Interface vs Type Alias: When to Use Which
  4. Creating and Initializing Classes Like a Pro
  5. Demystifying Public, Private, and Protected Modifiers
  6. The Power of Readonly and Optional Properties
  7. Inheritance Explained with Real World Examples
  8. When to Use Abstract Classes and When Not To
  9. Implementing Interfaces in Your Classes
  10. Why Composition Often Beats Inheritance
  11. Parameter Properties in Classes in Runtime
Section 21: Understanding Decorators in TypeScript
  1. What Decorators Really Are and Why They Exist
  2. Understanding the Decorator Execution Model
  3. Creating Class Decorators
  4. Creating Method Decorators
  5. Creating Property Decorators
  6. Creating Accessor Decorators
  7. Creating Parameter Decorators
  8. Building Reusable Decorator Factories
  9. Reflect Metadata API Explained
  10. Creating Custom Metadata with Reflect Metadata
  11. Building Validation Using Decorators and Metadata
  12. How Angular, NestJS, and TypeORM Use Decorators
  13. Legacy Decorators vs Standard ECMAScript Decorators
  14. What Is Changing in the New Decorator Proposal
  15. Mental Model of Decorators in TypeScript
Section 22: Using JSDoc with TypeScript
  1. What JSDoc Is and Why It Still Matters
  2. Adding Type Hints in JavaScript Files with JSDoc
  3. Setting Up checkJs and allowJs in tsconfig
  4. Using @param, @returns, and @typedef Tags Correctly
  5. Creating Custom Types and Objects with @typedef and @callback
  6. Working with Generics in JSDoc Comments
  7. Mixing JSDoc and TypeScript Files in One Project
  8. Generating Documentation Automatically from JSDoc
  9. Migrating from JSDoc to Real TypeScript Files Step by Step
Section 23: Advanced TypeScript Concepts
  1. Why TypeScript Is Not a Sound Type System
  2. Understanding Soundness and Unsoundness
  3. What Is Covariance?
  4. What Is Contravariance?
  5. What Is Invariance?
  6. Variance in Function Parameters
  7. Variance in Arrays and Collections
  8. Mental Model of Variance in TypeScript
Section 24: Hacking the TypeScript Compiler 🗿
  1. Exploring the TypeScript Codebase
  2. Cloning and Building TypeScript from Source
  3. Running a Custom TypeScript Compiler Locally
  4. Understanding the TypeScript Compiler
  5. Tracing a TypeScript Error Through the Source Code
  6. Adding Our Own Compiler Diagnostics
  7. Creating a Custom Compiler Error Message
  8. Implementing a New TypeScript Compiler Feature
  9. Adding a Custom Intrinsic Utility Type
  10. Creating Our Own Type-Level Keywords
  11. Modifying Type Inference Behavior
  12. Understanding How Built-in Utility Types Work
  13. How TypeScript Powers VS Code
  14. Exploring the TypeScript Language Server
  15. Building and Using Our Custom TypeScript Version
  16. Mental Model of the TypeScript Compiler