Without notes, state yesterday’s main idea and one unresolved question.
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— returnsany. Anything in the string becomes anything in your program.localStorage.getItem— returnsstring | null, written by a previous version of your code, or edited by the user in DevTools.- Form inputs —
HTMLInputElement.valueis always astring, even for<input type="number">. document.querySelector— returnsnullwhen 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:
- Load with existing saved data. Do all components appear?
- Add a component. Does it appear, and survive a refresh?
- Add an invalid component. Is it rejected with a message, and is nothing saved?
- Delete a component. Does it disappear from the list and from storage?
- Search for a term that matches, and one that matches nothing. Is the empty state shown?
- Filter by category, including the category with no items.
- Delete everything. Is the empty state shown rather than a broken table?
- 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.
- Finish the conversion. Every
.jsfile in the app should now be.ts, with the data model, parsing, rendering, and storage all typed. - Run the three
grepsearches. Record every hit innotes/day-35.mdwith the decision you made and the reason. - Get
npx tsc --noEmitto silence, thennpm run buildto succeed. Paste the real build output into your notes. - Run
npm run previewand work the eight-item checklist with the console open. Write the observed result for each — including any that fail. - 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.
- 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. - Send the reviewer prompt above on
git diff <day-28-hash>. Record which findings you reproduced and which you rejected. - 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
.jsto.tsand 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
asin 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.
- 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
asprovides no runtime protection? - 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
- 0–5 min Recall
- 5–20 min Learn
Read only the listed concept notes and official reference sections needed today.
- 20–48 min Build
Complete the inventory conversion, run the production build, and manually repeat the Week 4 test checklist.
- 48–55 min Explain and verify
Run the result, inspect evidence, and explain the data/control flow in your own words.
- 55–60 min Quiz and commit
Complete the quiz, record one lesson, and commit the verified change when applicable.
What to hand in
A typed build, clean console, and regression notes.
Working with AI today
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
Explain-back gate
Pass the quiz above to unlock completion.
Quiz + explain-back checks required.