JavaScript

Our first real experiment with TypeScript

JS

TypeScript has been building momentum for a couple of years, and we finally ran a real experiment with it this year, rewriting an internal admin tool rather than risking a client project on a technology the team was still learning. The tool itself was a reasonable size for an experiment — large enough to have genuine complexity worth type-checking, small enough that a failed experiment would not have been a serious cost.

The type errors TypeScript's compiler caught in the very first week of the rewrite were the strongest argument for it — several were genuine bugs already present in the original JavaScript version that had simply never been triggered by our existing usage patterns. One in particular stood out: a function that assumed an API response field was always present, which happened to be true for every case anyone had tested but was not actually guaranteed by the API's own documented contract, and which TypeScript flagged the moment we gave the response a proper type definition.

Where the friction actually was

Refactoring also felt noticeably safer; renaming a function or changing its signature immediately surfaced every call site that needed updating, instead of relying on grep and hoping. The friction we did encounter was mostly around typing third-party libraries that either had no type definitions available or had definitions that did not quite match how the library actually behaved in practice, which occasionally meant writing small workaround type declarations of our own rather than getting a clean experience out of the box.

We are not moving every client project to TypeScript yet — it adds a build step and a learning curve for less experienced developers, and a couple of team members newer to the codebase found the initial ramp-up genuinely frustrating rather than immediately rewarding. But for internal tools and for any client team that already has some TypeScript experience, we expect to recommend it more going forward, and we are planning a second, larger internal experiment next year before considering it a true default for client-facing work.

Measuring the actual time cost, not just the anecdotal feel

Beyond the qualitative sense that TypeScript caught real bugs, we tracked engineering time spent on the rewrite against our original JavaScript version's development time for comparable features, specifically to get past "it felt slower" or "it felt safer" as the only available evidence. The TypeScript version took modestly longer to write initially, roughly fifteen percent by our rough tracking, but needed noticeably fewer follow-up bug-fix commits in the weeks after each feature shipped compared to the equivalent JavaScript feature's history, which is the kind of tradeoff that is easy to undervalue if you only measure the upfront cost and never look at what happens afterward.

Choosing which projects to try it on next

Based on this experiment, we are prioritizing TypeScript adoption for internal tools and any new client project where the client's own team already has some prior exposure to it, rather than pushing it onto every project uniformly regardless of team familiarity. A client team with zero TypeScript experience taking over a TypeScript codebase after we hand it off is exactly the kind of maintenance risk we try to avoid creating, so team fit remains the deciding factor here just as it does in our React-versus-Vue decisions on other projects.

← Back to the journal

Have a project in mind?
Let’s talk.

Tell us where you are and where you want to go. We'll map the fastest route between the two.

Currently accepting new clients