TypeScript config and tooling · 8 / 8
lesson 8

Reading tooling type errors

The 14-line error message, decoded. Where to look first when overwhelmed.

~ 13 min read·lesson 8 of 8
0 / 8

You change one line. The build fails with fourteen lines of error output, six of which are paths into node_modules. You skim, find nothing recognizable, and start guessing. There's a better way to read these. The compiler is being precise — it's just verbose. Once you know where to look first and what each part of the message is for, the long errors stop being scary.

This lesson is the strategy for reading them.

Anatomy of a type error

Every type error has the same shape:

terminal output
src/checkout.ts:14:21 - error TS2345: Argument of type
'{ id: string; total: number; }' is not assignable to parameter
of type 'Order'.

Property 'currency' is missing in type
'{ id: string; total: number; }' but required in type 'Order'.

14   processOrder({ id: order.id, total: order.amount })
                  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Five parts:

  1. Location. src/checkout.ts:14:21 — file, line, column. The actual offending expression.
  2. Code. TS2345 — a stable identifier for this kind of error. Searchable. The same code always means the same thing.
  3. Headline. "Argument of type X is not assignable to parameter of type Y." The one-line summary.
  4. Reason. Indented below the headline. "Property currency is missing." This is the why.
  5. Pointer. The squiggle under the bad expression. Tells you exactly which characters the compiler objects to.

Read in this order: 1 → 5 → 3 → 4. Get the location, look at the squiggled expression in your file, then read the headline, then read the reason. The reason is usually the answer.

Tip

When an error feels overwhelming, ignore the headline and read the indented reason first. The indented part is the specific thing the compiler is saying about your specific code.

Reading the assignability trace

When the types are nested, the error grows a trace — a chain of "and inside that, this part doesn't match either."

terminal output
error TS2322: Type '{ items: { sku: string; qty: string; }[]; }' is not
assignable to type 'Cart'.

Types of property 'items' are incompatible.
  Type '{ sku: string; qty: string; }[]' is not assignable to type
  'CartItem[]'.
    Type '{ sku: string; qty: string; }' is not assignable to type
    'CartItem'.
      Types of property 'qty' are incompatible.
        Type 'string' is not assignable to type 'number'.

That looks like a wall of text. It's actually a clean drill-down. Each indent level descends one structural level into the type.

  • Top: the whole object doesn't match Cart.
  • One level in: the items property is the problem.
  • Two levels in: each item doesn't match CartItem.
  • Three levels in: the qty field is the problem.
  • Bottom: qty is string but should be number.

Read from the bottom up. The leaf of the trace is the actual mismatch. Everything above it is the path through your types to get there. Once you fix qty, the whole chain collapses.

src/cart.ts
/* before — qty was a string */
const cart = { items: [{ sku: "a", qty: "2" }] };

/* after — qty is a number */
const cart = { items: [{ sku: "a", qty: 2 }] };

That single change makes the entire fourteen-line error vanish. Long errors usually have a small fix — the chain just describes how deep the mismatch is buried.

check your understanding
You see a five-level assignability trace ending with "Type '0 | 1' is not assignable to type 'boolean'". Where is the bug?

Related diagnostics

After the main error, the compiler often appends a "Related" line that points to a different file — usually where the offending type is defined.

terminal output
error TS2345: Argument of type 'string' is not assignable to parameter
of type 'OrderId'.

src/types.ts:8:14
  8   export type OrderId = string & { __brand: "order" };
                   ~~~~~~~
  'OrderId' is declared here.

The related diagnostic shows you where OrderId is defined. That extra context is what makes branded types and other custom shapes understandable. The compiler is saying: "I know this looks like a string, but here's the declaration that says it's something more."

When an error mentions a type name you don't recognize, follow the related diagnostic to the source. Half the time the answer is right there in the type's definition — a comment, a stricter shape, or an exported helper that builds the value correctly.

check your understanding
A "Related diagnostic" points at a node_modules file. What does that usually mean?

Where to look first

When a build produces multiple errors, your instinct is to scan from the top. Resist that. The structure of tsc output is more strategic than chronological.

A repeatable triage:

  1. Count the errors. The summary line at the bottom is how many. If it's three or fewer, fix them in order. If it's twenty, something is wrong and the right move is to find the root cause first.
  2. Look for the "missing module" errors first. TS2307: Cannot find module 'X' errors often cascade — one missing import generates dozens of downstream "type not found" errors. Fix the resolution, half the noise disappears.
  3. Look for the most-cited file. If a single file appears in twelve errors, that's where the bug probably lives. The other eleven are downstream effects.
  4. Read the first error of any category. If you have eight TS2345 errors all referencing the same type, the first one is usually the most specific. The rest are repetitions at different call sites.
terminal output
Found 23 errors in 4 files.

Errors  Files
  14  src/types.ts
   6  src/cart.ts
   2  src/orders.ts
   1  src/index.ts

The summary at the bottom of tsc output tells you exactly where to look. types.ts has fourteen errors — start there. The single error in index.ts is almost certainly downstream of the bigger problems and won't be fixable until upstream is clean.

Tip

Fixing one upstream error often deletes ten downstream ones. After every fix, re-run tsc --noEmit and watch the count drop. Don't fix the same error in twenty places when one fix at the source will do.

check your understanding
You make one change to a type and suddenly have 47 errors. Most of them say "Type X is not assignable to type Y." What's the most likely shape of the fix?

Three tactics for hard errors

When the message still doesn't help, three moves usually get you unstuck.

1. Hover the suspicious value. In your editor, hover the variable involved in the error. The popup shows its full inferred type. Often the inferred type is wider or narrower than you expected, and that mismatch is the bug.

2. Annotate explicitly to localize the failure. If const order = await getOrder(id) produces a type error two lines later, add an explicit annotation: const order: Order = await getOrder(id). Now the error happens at the assignment, not later. Localizing the error makes the cause obvious.

3. Search the error code. TS2345, TS2322, TS2307 — these are stable across versions. Searching the code along with a few key terms from the message often finds someone with the same pattern. The TypeScript docs and the issue tracker both reference these codes.

src/checkout.ts
/* before — error happens at processOrder(), confusing */
const order = await getOrder(id);
const tax = calcTax(order);
processOrder(order);   /* error here */

/* after — error happens at assignment, obvious */
const order: Order = await getOrder(id);   /* error here */
const tax = calcTax(order);
processOrder(order);

Adding the annotation moves the error closer to its source. The compiler now complains at the line where the wrong shape enters your code, not at the line where it's eventually used. That distance closes the gap between "where the symptom appears" and "where the bug is".

check your understanding
The error says "Type 'undefined' is not assignable to type 'string'", but you're sure the value is set. You hover the variable and the editor shows it as string | undefined. What's the next move?
check your understanding
You see TS2307: Cannot find module 'lodash'. The package is installed. lodash ships no types of its own. What is the most likely fix?
← prevfinish course →
KeepLearningcertificate
for completing
TypeScript config and tooling
0 of 8 read