Engineering

Why TypeScript Is Still the Right Call in 2025

The debate was never really about types. It was about whether you trust your team to remember every decision they made six months ago.

Rohan Desai·10 March 2025·4 min read

Three years after TypeScript became mainstream, there is still a persistent faction of developers who treat it as optional - a preference, like tabs over spaces. Having shipped production systems in both TypeScript and plain JavaScript at scale, I want to make the case that TypeScript is not a style preference. It is a risk management decision.

The argument against is not wrong, it's just incomplete

The standard objection goes like this: TypeScript adds ceremony. You spend time writing types instead of writing features. In a fast-moving startup, that overhead is a competitive disadvantage.

This is a fair description of the short-term cost. It is also an incomplete description of the total cost.

What the argument omits is the category of bugs that only appear in large codebases maintained by multiple people over long time periods. These are not bugs introduced by carelessness. They are bugs introduced by context loss - by the gap between what a function was designed to do when it was written and what a caller assumes it does six months later.

TypeScript does not prevent you from writing bad code. It prevents a specific, high-cost category of mistake: the runtime surprise that emerges from a misread interface contract.

What we actually see in production

At HeapiFy, we have inherited enough codebases to have a clear empirical view of this. The pattern is consistent:

JavaScript codebases below approximately 20,000 lines are usually fine. The original author is still on the project, the surface area is small, and the mental model is intact.

Above that threshold, things diverge sharply. JavaScript codebases tend to accumulate a layer of defensive programming - if (thing && thing.prop && thing.prop.value) chains, any-shaped objects passed between functions, flag parameters that mean different things depending on call site. The code still works. It just becomes increasingly expensive to change without breaking something.

TypeScript codebases at the same size tend to be more legible because the contracts between modules are explicit. You can follow a data structure through ten layers of transformation and know, with confidence, what shape it has at each step. Refactoring is less frightening because the compiler surfaces breakages instead of hiding them until runtime.

The "you can always add types later" trap

One of the most expensive decisions we see is the decision to start in JavaScript and add TypeScript later. This almost never happens on the timeline that teams expect.

The reality is that migrating an active codebase to TypeScript means introducing types during a period when the codebase is still changing. You end up with a hybrid that has all the cost of TypeScript (build step, type definitions, tooling) and none of the benefit (because the any escape hatch is used liberally to unblock the migration).

The time to make the TypeScript decision is before you write the first line. The cost of starting with TypeScript is a few extra hours in week one. The cost of migrating to TypeScript is weeks of engineering time with a codebase in an unstable intermediate state.

What strict mode actually catches

If you are going to use TypeScript, use strict: true. The non-strict mode catches a subset of errors and gives you a false sense of coverage.

With strict: true enabled, the compiler catches:

  • Implicit any - forces you to be explicit about untyped values
  • Strict null checks - eliminates the billion-dollar mistake
  • Strict function types - catches callback signature mismatches
  • No implicit this - prevents subtle context binding bugs

In our experience, strict mode eliminates roughly 30–40% of the integration bugs we used to find in code review and testing. These are not dramatic bugs. They are the small, tedious ones that are expensive precisely because they are hard to find manually and easy to prevent mechanically.

A practical recommendation

If you are starting a new project:

  • Use TypeScript with strict: true from day one
  • Define your domain types before you write implementation code - treat your types/ directory as documentation
  • Do not use any except at system boundaries (external API responses, JSON parsing output) and cast out of it immediately
  • Invest in good IDE integration - the feedback loop with TypeScript is only valuable if it is fast

The ceremony is real. The upside is not that TypeScript makes you a more productive developer in week one. It is that your team in week forty can still move at close to week-one velocity.

That is the actual return on investment.

Stay Current

Engineering notes, when we have something worth saying.

No weekly newsletters. No content marketing. When a post goes up, you'll get it.