Debugging TypeScript
When TypeScript yells at you, the error messages can look like ancient hieroglyphs. Learning to read them is a critical skill.
The mental model
TypeScript errors are heavily nested because types are heavily nested. The compiler isn't just telling you what failed; it is showing you its entire thought process of why it failed, tracing all the way down the object tree until it finds the exact mismatch.
Always read TypeScript errors from bottom to top.
type User = { profile: { age: number } };
const u: User = { profile: { age: "25" } };
The error output will be:
Type '{ profile: { age: string; }; }' is not assignable to type 'User'.
Types of property 'profile' are incompatible.
Type '{ age: string; }' is not assignable to type '{ age: number; }'.
Types of property 'age' are incompatible.
Type 'string' is not assignable to type 'number'.
The first line is useless (the entire object is wrong). The last line tells you exactly what to fix (string vs number on age).
The Hover trick
The fastest way to debug a complex inferred type is just to hover over the variable in your IDE. If a complex generic or utility type isn't doing what you expect, assign it to a temporary variable or type alias and hover over it.
// Complex mapped type
type Formatted = Record<"a" | "b", Partial<{ id: number }>>;
// Hover over 'test' to see exactly what TS evaluated this to!
type test = Formatted;
Using @ts-expect-error
Sometimes you know a type error is wrong due to a limitation in a library, or you specifically want to test an invalid input.
Do not use // @ts-ignore. It completely blinds the compiler to that line forever.
Use // @ts-expect-error instead. It silences the error, BUT if a future TypeScript update (or library fix) resolves the issue so the line would compile cleanly, TypeScript will throw an error telling you to remove the // @ts-expect-error comment.
When facing a massive TypeScript error block, ignore the top and scroll straight to the bottom. The last indented line usually contains the actual property mismatch.