Spotify
Course Description
Master TypeScript and get better results from AI generated code. Explore advanced techniques like generics, conditional types, and discriminated unions, while gaining the skills to spot subtle mistakes and craft better prompts. Become the TypeScript expert on your team and take ownership over your type system.
Prerequisite: Solid understanding of TypeScript or our
TypeScript Fundamentals course.
Preview
Course Details
Published: July 30, 2026
Learn Straight from the Experts Who Shape the Modern Web
Your Path to Senior Developer and Beyond
- 300+ In-depth courses
- 24 Learning Paths
- Industry Leading Experts
- Live Interactive Workshops
Table of Contents
Introduction
Section Duration: 4 minutes
Adam Rackis introduces the course by explaining why TypeScript's foundational role makes it uniquely risky to get wrong when generating code with AI. He previews the workshop's dive into core features like generics and mapped types, which will help viewers prompt AI more effectively and catch its mistakes.
TypeScript Basics
Section Duration: 48 minutes
Adam explains the difference between structural typing and nominal typing, emphasizing that in structural typing, types define the structure that valid values will hold rather than just the valid variables a value can be. He also delves into the concept of types as sets of valid values, using examples like literal values and unions to illustrate how types can be defined.
Adam covers the basics of TypeScript, including type inference, the any type, unknown type, and never type. He also explains how to type functions, use unions, and create types for literal values like true and false.
Adam covers a variety of real-world practical tips and tricks in TypeScript, emphasizing the use of the type of operator to extract static types from runtime values efficiently. He then explores the importance of relying on inferred typing in functions, showcasing how TypeScript can accurately infer types without the need for manual declaration in most cases.
Adam demonstrates how to use TanStack form, explaining the process of setting default values and utilizing the use form hook to create a form variable with statically typed properties like field components. He then guides students through a technique to simplify complex form types by using a two-step process involving TypeScript utility types like return type, enabling static checking and efficient code organization.
Adam explains the importance of exporting types when creating public APIs, emphasizing the need to export types for both function parameters and return types. He demonstrates how to use TypeScript utility types like `return type` and `parameters` to extract necessary types from functions, enabling proper typing without manual intervention.
Adam walks through the concept of conditional return types in TypeScript functions, explaining how TypeScript infers union types for conditional return values and how to explicitly declare return types to enforce specific contracts. He then demonstrates a two-step process using a custom lookup object to ensure an array contains unique keys from a given type, showcasing how TypeScript can enforce type safety throughout the process.
Generics
Section Duration: 48 minutes
Adam explores the concept of generics, comparing them to template systems in languages like C++. He breaks down how generics allow passing types as parameters, demonstrating the flexibility they offer for working with various data types, including built-in and user-defined types.
Adam explains how to properly handle generics in React components, demonstrating the importance of adding a generic type to the component and utilizing parentheses and a comma to avoid syntax clashes with JSX. He then outlines two approaches to typing the component, either manually typing the props or using the built-in type `FC` for a fully typed component.
Adam explores the concept of generics, demonstrating how they can be used to maintain specificity in TypeScript by adding a generic argument to a method. He breaks down the process of using a generic constraint to ensure that the type parameter is limited to a specific type, such as a catalog item, preventing unintended data types from being accepted.
Adam explains how to ensure that various functions in a codebase take the same arguments by creating a loader function that enforces argument consistency. He demonstrates using TypeScript tricks like 'as const' and spreading to infer specific tuple types, ensuring type safety without burdening other engineers with intricate details.
Adam demonstrates how to use Zustand for state management in React, showing how to create a store with initial values and selectors to access specific state slices. He explains the importance of manually adding generics to ensure correct type inference when using custom selectors in Zustand.
Adam demonstrates how to enhance a groupBy function by introducing generics to ensure more precise typing. He guides students through enforcing valid key names using key of T, resulting in a record of string values for each city and an array of users for each city.
Adam demonstrates how understanding TypeScript features, like generics and inferred typings, can streamline code changes and make AI integration easier in software engineering tasks. He explores leveraging AI to refactor code by asking for specific constraints and type inferences, showcasing the benefits of knowing how to interact effectively with AI tools in development workflows.
Unions
Section Duration: 53 minutes
Adam Rackis explores TypeScript unions in depth, from narrowing and intersections to why enums should be avoided in favor of string literal unions. He then demonstrates discriminated unions through a cat-and-dog example, contrasting the fragile "in" operator with proper discriminator properties, and shows how this knowledge lets you prompt AI to refactor a union correctly in seconds.
Adam Rackis walks through more type narrowing techniques that TypeScript recognizes from native JavaScript, including typeof for built-in types and instanceof for class instances. He closes with a practical example using Array.isArray to narrow between a single item and an array of items.
Adam demonstrates how to create custom type guards in TypeScript to manually narrow types within a union, using functions like 'animal is lion' and 'animal is cat' to check and narrow down specific types based on conditions. He then explores the use of type guards in array methods like filter to ensure type safety and how TypeScript's type inference can simplify the process by recognizing type guards like 'x is number' for filtering arrays.
Adam demonstrates how to enforce exhaustive type checking in TypeScript by narrowing down unions until only 'never' is left, ensuring every possible type is covered. He shows a clever trick of using an 'assert never' function to force coverage of all possibilities, preventing errors when adding new types to the union.
Adam explores excess property checking in TypeScript, demonstrating how assigning object literals to typed variables triggers errors when extra properties are present, showcasing the use of the satisfies keyword to enforce strict type structure without allowing wider types to be inferred. He guides students through understanding how this feature works and its practical application in maintaining type integrity.
Conditional Types
Section Duration: 51 minutes
Adam explores conditional types in TypeScript, demonstrating how to create basic conditional types using ternary operators to return different types based on conditions. He then delves into more complex examples, showcasing how to use the infer keyword to extract specific types from generic arguments, enforcing constraints to ensure that certain types are passed into the conditional types.
Adam demonstrates how to work with AI models to generate types for React components based on specific conditions, showing examples of prompts and results obtained. He then explores the importance of understanding and guiding the output towards simpler solutions, emphasizing the need to comprehend generated types for future use.
Adam demonstrates how to implement custom conditional types in TypeScript, starting with creating a get return type that mimics the behavior of built-in return types. He then guides students through creating a get parameters type, ensuring it only works with functions and comparing the custom types to TypeScript's built-in versions.
Adam demonstrates how passing a union to a conditional type in TypeScript results in the conditional type running with each member of the union and then unioning all those results together. He breaks down how the conditional type kicks out any nevers it encounters along the way, providing a clear understanding of how the process works graphically and through code examples.
Adam demonstrates how to write type assertions for unit testing complex types in TypeScript, emphasizing the simplicity of using type assertions over testing frameworks like Jest or Vtest. He explores creating type helpers to verify if two types match, utilizing conditional types to achieve the desired behavior and avoid union type issues.
Adam walks through the process of implementing a type in TypeScript that checks if one tuple type is a subset of another, explaining the algorithm using a Pac-Man analogy to compare and process tuple members recursively. He demonstrates how to split tuple types, infer their heads and the rest of the items, and recursively call the function to check for type matching, emphasizing the importance of syntax and type extensions in TypeScript.
Adam explores the concept of managing argument lists in prefetch and load calls, emphasizing the importance of passing the longer list of arguments to a single load method. He demonstrates how to determine which argument list is longer and ensure they are subsets of each other to handle different scenarios effectively.
Advanced Techniques
Section Duration: 54 minutes
Adam explains the concept of function overloading, showcasing how to create multiple versions of a function based on the types of their parameters. He contrasts using conditional types versus function overloads in TypeScript, demonstrating how function overloads provide distinct APIs without the confusion of unions.
Adam explores the concept of template literal types, demonstrating how to interpolate values and types inside a template literal type, allowing for autocomplete based on the values interpolated from a union. He then breaks down how to manipulate literal string types, filter them, and use them in functions, showcasing the niche yet powerful capabilities of template literal types in TypeScript.
Adam explains the concept of variance, covering covariance and contravariance in types, showcasing how providing more specific or less specific types than what is asked for can impact variables, function arguments, and return types. He demonstrates how this understanding is crucial when working with function types, particularly in scenarios like React event handlers, where treating a more specific event type as a generic one can be valid and useful.
Adam demonstrates how TypeScript’s map types enable helpful type transformations, including filtering unions, remapping keys with template literals, converting object properties, and projecting values into unions.
Adam demonstrates how to strip functions and return types from an API object using TypeScript utility types like `return type` and `Omit`. He then explores filtering out specific properties based on function return types, cautioning against incorrect assumptions due to TypeScript's variance in return types.
Adam guides students through implementing a map type that converts date properties to strings while keeping other types unchanged. He also expands on the example by generating a similar solution from an agent to highlight the importance of understanding what's beging generated.
Adam demonstrates how to create a helper type for string or number keys, looping through keys and filtering out invalid ones to ensure only valid keys are allowed for grouping. He then refines the group by type, excluding certain keys like 'hobbies' and ensuring TypeScript compatibility by casting as string or number where needed.
Wrapping Up
Section Duration: 5 minutes
Adam wraps up the course by walking through an advanced mapped type exercise that filters and renames object keys using template literal types and conditional infer clauses. He uses an unexpected result along the way to reinforce a key lesson: even when TypeScript can handle deeply nested logic, it's worth stepping back for a simpler solution.
Earn a Completion Certificate
After completing this course, you'll receive a certificate of completion that serves as proof of your achievement, showcasing your expertise, and commitment to professional development. You can easily share this certificate on your LinkedIn profile to highlight your new skills and demonstrate continuous learning to potential employers and professional connections.
