13. TypeScript and JavaScript experience
Answer as submitted
“JavaScript: 20+ years. TypeScript: 8+ years of continuous professional use.”
Expanded answer
JavaScript 20+ years — from ES3/ES5 and DOM-era engineering through modern ES2015+: modules, closures and the event loop, promises and async/await, functional composition, WebSockets/real-time flows, Node.js services and Jest-based testing. TypeScript 8+ years of continuous professional use — strict compilation, discriminated unions and generics, branded types, exhaustive switches, typed API clients, typed lint rules and typed Angular/React components, with runtime validation only where data crosses a boundary. The two overlap: TypeScript above all is JavaScript whose behaviour at runtime still has to be understood.
| Decision | Where it is applied | Why it is done this way |
|---|---|---|
| Strict compilation | strict + noUncheckedIndexedAccess | Null and undefined mistakes are caught at build time, not by a user. |
| Domain modelling | discriminated unions, generics, brands | Illegal states become unrepresentable and every branch must be handled. |
| Boundary validation | schema parse on HTTP, queue and storage input | Types are erased at runtime, so untrusted data is proven before use. |
| Async discipline | allSettled, timeouts, cancellation, async iterators | A slow dependency degrades one part instead of hanging the request. |
| Error shape | Result<T, E> instead of thrown exceptions | The failure branch cannot be forgotten by a caller. |
| Tooling | typed ESLint, Prettier, tsc --noEmit in CI | Consistency is enforced by the pipeline, not by review alone. |
| Bundle budget | Vite/esbuild budgets in the pipeline | Payload size is a measured constraint as the application grows. |
Live TypeScript workflow proof
The running component below changes its configuration/result view through real event binding. Select a step to see the decision, the reasoning behind it, and the measurement that proves it.
Choose a TypeScript step
Select a step to inspect the decision, the reasoning and the measured result.
$ "strict": true, "noUncheckedIndexedAccess": true, "exactOptionalPropertyTypes": true
Strict mode is non-negotiable: null checks, no implicit any and verified indexed access, so type errors surface at build time instead of in production.
tsc: 0 errors · 0 implicit any any occurrences in src: 3 (all at the infrastructure boundary)
How the years translate into practice
any count at the infrastructure boundary only; model with unions so illegal states cannot be constructed; parse everything that crosses a boundary; write async code with explicit timeouts, cancellation and partial-failure handling; prefer a Result over a thrown exception on expected failure paths; and let the pipeline — typed lint, tsc --noEmit and bundle budgets — enforce the standard. Deep JavaScript knowledge is what makes this possible: the type system is a design tool, not a substitute for understanding the runtime.
Source files
Select a file to inspect the proof with syntax highlighting and line numbers. The first file is the code running the component above; the other two are the production shapes of the same practice.
Acceptance criteria
- States the years of experience for JavaScript and TypeScript separately.
- Distinguishes strict compilation, modelling, boundary validation, async and tooling.
- Shows an interactive proof of choosing a TypeScript step and reading its measurement.
- Keeps runtime validation at the boundary and the failure branch in the type.
- Defers monorepo orchestration, untyped-codebase migration and render strategies to a later topic.