0 / 91
Week 5 · Day 35 of 91

Week 5 typed application review

TypeScript, Packages, and Tooling

Objective

Finish the TypeScript conversion and verify behavior did not change unintentionally.

TypeScript is similar to design-rule checking: it catches invalid connections before runtime but cannot prove system behavior.

  • compiler as feedback
  • runtime validation still required
  • build and manual regression checks

Why this matters

You have spent six days changing how your inventory app is written without intending to change what it does. Today you prove that. A refactor that quietly alters behaviour is worse than no refactor, because you now trust code that misleads you. By the end of the hour you will have a clean type check, a production build, a browser console with nothing red in it, and written regression notes saying which behaviours you checked and what you found.

The compiler as feedback, not as a grade

npx tsc --noEmit printing nothing feels like a pass mark. It is not. It is one instrument reporting one class of fault.

Treat the compiler the way you treat a continuity tester: it answers a narrow question quickly and completely, and it answers nothing else. Used well, its errors are a worklist, not a scoreboard. When you convert a file and get thirty errors, that is thirty places where the code was already ambiguous — the compiler did not create them, it revealed them. Work down the list; do not silence it.

Silencing takes three forms, and today you hunt all of them:

  • any — checking off for that value and everything derived from it.
  • as — a type assertion; you overruling the compiler with no runtime check.
  • @ts-ignore / @ts-expect-error — comments that suppress the error on the next line.

Each is occasionally justified and each must be justified in writing. An unexplained one is a bug someone has not met yet.

DRC clean is not a working board

Design-rule checking confirms the layout is manufacturable: no shorted nets, no undersized traces, no footprint mismatches. A DRC-clean board can still oscillate, brown out, or amplify nothing at all, because DRC never modelled behaviour — only connection validity. A clean tsc run is a DRC pass. It says your connections are valid. Whether the circuit does the job is answered on the bench, by powering it up and measuring.

Runtime validation is still required

This is the week's most important honest limitation, so state it plainly: TypeScript cannot replace runtime validation, because external and runtime data still require checking.

Types are erased at build time. The JavaScript that runs in a browser has no idea what Component was. So every value crossing into your program from outside is unchecked unless you check it:

  • JSON.parse — returns any. Anything in the string becomes anything in your program.
  • localStorage.getItem — returns string | null, written by a previous version of your code, or edited by the user in DevTools.
  • Form inputs — HTMLInputElement.value is always a string, even for <input type="number">.
  • document.querySelector — returns null when nothing matches, whatever type you asked for.
  • From Week 6, network responses — a server that changed last Tuesday does not consult your types.

The rule is a boundary: validate once, where data enters, and trust it inside. That is exactly what Day 32's parseComponent and loadComponents are for, and today you confirm every entry point goes through them.

Goods inwards

A factory inspects parts at the loading bay, not at every workstation. Once a reel has passed incoming inspection, the line trusts it. Your parse module is the loading bay; everything past it may assume the data is what it claims to be — precisely because something checked.

The most tempting shortcut of the week

const items = JSON.parse(raw) as Component[]; compiles, reads nicely, and validates nothing. If the stored array holds one malformed record, your app breaks at render time with a message pointing at the wrong file. Search your project for as today and delete every one you cannot justify out loud.

Build and manual regression checks

A regression is a behaviour that used to work and no longer does. You have no automated tests yet — those come in Week 11 — so today's check is manual, deliberate, and written down.

Two gates, in order.

The build gate. npm run build runs tsc && vite build, so a type error stops it before any output is produced. It also catches things tsc --noEmit alone will not: a missing import path, an asset that does not exist, a module that cannot be resolved. A build that succeeds is a stronger claim than a type check that is silent.

The behaviour gate. Run the built output with npm run preview and work through a fixed list — the same list, every time, so results are comparable. Reuse your Week 4 demo checklist:

  1. Load with existing saved data. Do all components appear?
  2. Add a component. Does it appear, and survive a refresh?
  3. Add an invalid component. Is it rejected with a message, and is nothing saved?
  4. Delete a component. Does it disappear from the list and from storage?
  5. Search for a term that matches, and one that matches nothing. Is the empty state shown?
  6. Filter by category, including the category with no items.
  7. Delete everything. Is the empty state shown rather than a broken table?
  8. Corrupt the stored data by hand in DevTools, then reload. Does the app show an error state instead of a blank screen?

Keep the browser console open throughout. A clean console is part of today's deliverable: no red errors, no yellow warnings you cannot explain. A warning you have decided to ignore is fine; a warning you have never read is not.

Walkthrough

cd ~/fullstack-journey/inventory-ts
git status

Start clean, as on Day 34. Now audit the escape hatches. grep searches file contents; -r means recursively through folders and -n prints line numbers.

grep -rn ": any" src
grep -rn " as " src
grep -rn "ts-ignore\|ts-expect-error" src

Every hit is a decision to make now: replace it with a real check, or write a one-line comment above it saying why it is safe. No silent survivors.

npx tsc --noEmit
npm run build
vite v8.2.0 building client environment for production...
✓ 9 modules transformed.
dist/index.html                  0.45 kB │ gzip: 0.29 kB
dist/assets/index-CsUDhMuy.css   4.10 kB │ gzip: 1.46 kB
dist/assets/index-Na4_thdC.js    4.49 kB │ gzip: 2.02 kB

✓ built in 317ms

Then serve the real output and walk the checklist:

npm run preview

Finally, look at the week as one change. Find your Day 28 commit and diff against it:

git log --oneline
git diff <that-hash> --stat

The --stat view is the honest summary of what a week of "just adding types" actually touched.

Checkpoint

For each of the eight checklist items, you should be able to say what you observed, not what you expect. "Search with no matches shows 'No components found'" is an observation. "Search works" is a hope.

How to use AI today

Today's mode is reviewer. A review should produce specific, actionable findings with evidence — a file, a line, and what goes wrong — not praise and not a rewrite. Give it the whole week's diff, because behaviour changes hide between files.

Reviewer mode, on the full week diff

"Review the final diff for unsafe assertions, any usage, duplicated types, and behavior changes." Then reproduce each finding yourself before acting on it. An unreproduced finding is a rumour, and a fix you apply without reproducing is a second change you cannot explain.

Your turn

Produce the deliverable: a typed build, a clean console, and regression notes.

  1. Finish the conversion. Every .js file in the app should now be .ts, with the data model, parsing, rendering, and storage all typed.
  2. Run the three grep searches. Record every hit in notes/day-35.md with the decision you made and the reason.
  3. Get npx tsc --noEmit to silence, then npm run build to succeed. Paste the real build output into your notes.
  4. Run npm run preview and work the eight-item checklist with the console open. Write the observed result for each — including any that fail.
  5. Fix any regression you found, one at a time, re-running the build and the affected checklist item after each fix. Note what broke and why the type system did not catch it.
  6. Confirm one runtime protection by experiment: open DevTools, set your storage key to not json, and reload. Record what the user sees. If it is a blank page or a console error, your boundary is not doing its job — fix it.
  7. Send the reviewer prompt above on git diff <day-28-hash>. Record which findings you reproduced and which you rejected.
  8. Commit the week with a message naming what changed and what deliberately did not.

You are done when

npm run build succeeds, the console is clean through all eight checks, and notes/day-35.md lists an observed result for every item plus a justified decision for every any and as.

Common pitfalls

  • Treating a silent compiler as "tested". It never ran your code. Types agreeing and behaviour being correct are different claims.
  • Converting and refactoring in the same pass. Rename .js to .ts and add types first; make logic improvements as separate commits. Otherwise a regression has two possible causes.
  • Testing only the happy path. Empty list, no search results, corrupt storage, and rejected input are where conversions break.
  • Leaving as in the parsing layer. That is the one place where an assertion is most likely to be wrong, because the data genuinely comes from outside your program.

Verify it yourself

Open today's reference, the TypeScript Handbook, and find its pages on type assertions and on what the compiler emits.

  1. Find the Handbook's statement about type assertions being removed at compile time. Copy it into your notes. Does it support this lesson's claim that as provides no runtime protection?
  2. The Handbook describes a restriction on which assertions TypeScript will allow, and an escape from it involving unknown. Find both, and say what that restriction does not protect you from.

Write both answers into notes/day-35.md and commit. Next week you leave the browser and write a server — and every rule about validating data at the boundary matters more there, not less.

The hour

  1. 0–5 min Recall

    Without notes, state yesterday’s main idea and one unresolved question.

  2. 5–20 min Learn

    Read only the listed concept notes and official reference sections needed today.

  3. 20–48 min Build

    Complete the inventory conversion, run the production build, and manually repeat the Week 4 test checklist.

  4. 48–55 min Explain and verify

    Run the result, inspect evidence, and explain the data/control flow in your own words.

  5. 55–60 min Quiz and commit

    Complete the quiz, record one lesson, and commit the verified change when applicable.

What to hand in

Deliverable

A typed build, clean console, and regression notes.

Working with AI today

AI as skeptical reviewer

Provide existing work and ask for concrete defects, risks, missing tests, and unsupported assumptions—not praise.

Review the final diff for unsafe assertions, any usage, duplicated types, and behavior changes.

References

End-of-day quiz

Q1 Can TypeScript replace runtime validation?
Q2 Which result best proves today’s work is complete?
Q3 What should an AI code review primarily produce?

Explain-back gate

Pass the quiz above to unlock completion.

Quiz + explain-back checks required.