The fallacies of “the TypeScript tax”

Mozafar Hayder
7 min readNov 29, 2022

--

This post is a response to The TypeScript tax by Eric Elliott.

The article analyses the question of whether teams should adopt TypeScript reaching a conclusion that:

I will not use the current version of TypeScript in my next large scale application, because the larger the project is, the more the costs of using TypeScript compound.

The writer insists that all the findings still apply four years after writing it. He argues that the cost (the tax) of using TypeScript outweighs the benefits, and he sets a framework (a set of measures) to evaluate the Return of Investment for using TypeScript. He promotes other practices instead of TypeScript such as following TDD, Design and Spec Reviews and Code Reviews.

I disagree with the conclusions, but this is normal in a subjective topic. What pushed me to write this response though is the methodology for reaching these conclusions; The article claims to follow a methodical approach to reach conclusions, and due to its popularity, I often find myself having to argue against its findings which are quoted as hard data and facts. However, it has many inconsistencies and is full of cherry-picked evidence and logical fallacies.

The dimensions

The article starts by setting out what appears to be a scientific framework for comparing different techniques and technologies, including TypeScript, based on a set of dimensions. It then proceeds to score TypeScript against each of these dimensions (solely based on personal opinion and experience).

The dimensions are fundamentally flawed. For example, having “Typing Overhead” as a dimension is misleading.

In practice, the overhead is irrelevant with modern IDEs with autocomplete, inference and other features. Moreover, the typing overhead for types is much less than the typing overhead for writing test descriptions in natural language, or writing comments, documentation, maybe even PR descriptions. What constitutes overhead?

This metric is an irrelevant dimension without the extra context, and skews the “score” unfairly. A real issue might be the syntactical noise but that is glossed over, but as for the “time spent typing, testing, debugging, and maintaining type annotations”, the same applies — even more so — to writing and maintaining tests.

Then Recruitment is also tackled as a metric. Recruitment — as an objective dimension — depends largely on the type of the organisation and your team’s recruitment strategy: are you recruiting only seniors, or juniors and training them? does your organisation allow for learning on the job, collaboration, mentoring, and knowledge-sharing?

If the organisation only hires seniors and “rockstars”, or has no place for learning, and does not consider juniors, then the recruitment problems (and the organisation’s culture) run deeper than the choice of a technology.

It’s also important to remember that the article is not comparing TypeScript vs JavaScript, it’s rather comparing TypeScript vs “JavaScript paired with tools built for native JavaScript”, so the question (and the scoring) should be is it really easier to find JS developers with good TDD experience than ones with TypeScript experience?

Recruitment is hard, regardless of language or technology. Hasty generalisations don’t make it easier.

The fallacies: The inconsistent comparison

A fallacy is the use of invalid or otherwise faulty reasoning, or “wrong moves,” in the construction of an argument which may appear stronger than it really is if the fallacy is not spotted.

But let’s take a BIG leap of faith and trust that these dimensions and the scores are “objective data”, then the article does not even try to score the alternative (“Not just JavaScript, but JavaScript paired with tools built for native JavaScript”) against the same set of dimensions. This is the first logical fallacy: the inconsistent comparison.

If we are rating TypeScript’s learning curve and ongoing mentoring, then we need to also rate TDD’s learning curve and ongoing mentoring.

In my view, the cost of the initial training and ongoing mentorship for TDD, is higher than TypeScript. TypeScript has good documentation (now in 2022), and its knowledge set — as a language — is much limited than TDD and testing in general. I view TypeScript as a science, and TDD (and testing in general) as an art. That’s why we talk about using the correct type, but talk about having a good test — not the correct test.

In general, it takes very little to learn a language, compared to the training, mentorship and real-life experience you need to adopt a practice effectively, especially one like TDD.

But regardless of my personal opinion, the fundamental flaw in the article is that it scores TypeScript against this dimension while omitting doing the same for the alternative. The comparison is inconsistent.

The false equivalence fallacy

The second fallacy is the “False equivalence” — describing two or more statements as virtually equal when they are not, or comparing “Apples and Oranges”.

Comparing “TypeScript” (a language) against “JavaScript paired with tools built for native JavaScript”, mentioning a set of techniques such as TDD, spec and design docs, and code reviews among tools like Babel and linters, is not a sound comparison. The writer is indeed comparing apples and oranges.

First, these techniques are not related to a language, and most teams would use some or all of these practices, whether they’re using TypeScript or not. A real scientific approach would have involved answering the question: if all these other bug prevention techniques and practices were present, then which choice would provide a better ROI: Plain JavaScript or TypeScript.

Alleged Certainty fallacy

Asserting a conclusion without evidence or premises, through a statement that makes the conclusion appear certain when, in fact, it is not.

In most cases, if you can gain a significant benefit from TypeScript in your refactoring, that’s often a code smell indicating that your code is too tightly coupled.

This statement is misleading. It is often mentioned as a given in discussions about TypeScript, but digging slightly under its surface, you will realise it is a non-statement. The writer should have at least provided some examples and a deeper analysis for such a conclusion.

In practice, the patterns that cause coupling nowadays are largely dictated by design choices such as the framework used and state management solution. But even when they are not, TypeScript does not affect how coupled the code is.

Moreover, if you build a tightly-coupled badly designed application, it’s very likely that you also built a tightly-coupled badly designed test suite that makes refactoring impossible, or even worse, no test suite at all. In the latter case, TypeScript gives you a relatively solid place to start: you can refactor knowing that at least TypeScript is catching 20% of the issues (according to the article). Don’t smirk at the 20%, your choices are either 20% confidence, or 0%!

Lastly, using TDD itself — in a dogmatic inflexible way — leads to tests that are highly coupled with implementation details. This, in turn, makes refactoring harder, and is a code/quality smell. I loved TDD (from first-sight unlike TypeScript) and adopting it was the biggest improvement I had in the quality of my code in my career. The second biggest improvement was when I learned when not to follow TDD. Nowadays, my approach of choice is to Write Tests, Not many, Mostly Integration by Kent C. Dodds. This approach makes refactoring easier, not TDD, nor any of the approaches described in the article.

The false dilemma

Another fallacy in the article is the False Dilemma: two choices are given when in fact there are three or more options.

The article implies that our choices are mutually exclusive. The tools and techniques presented are not absent in TypeScript, nor there is evidence that teams that use TypeScript have a tendency to ignore these other bug prevention measures.

Nutpicking Fallacy

Nutpicking fallacy is when someone presents an atypical or weak member of a group as if they are a typical or strong representative.

Some people argue that if you have static types, you don’t need to worry about writing so many tests.

I personally never heard this opinion before.

On the contrary, a conversation about adopting TypeScript is generally a sign of a certain level of maturity in an organisation, that — at least — the organisation is going out of its comfort zone to ensure quality. That level of maturity also typically means that there is a healthy level of test coverage (whether it’s using TDD or not), or at least an awareness of the lack of it.

It also typically means that some of the other practices are already implemented: controls such as static code analysis (linting) and code formatting, code reviews, continuous integration and maybe design reviews as well. I don’t remember the last time I worked in a place that these measures were not in place. I also have never been in an organisation where the conversation considers TypeScript as an alternative to testing and these other quality measures, it is always considered as an extra measure.

In conclusion, the logical arguments presented in the article lack logic.

But that in itself does not mean the conclusion is wrong. The general objective of evaluating the ROI of TypeScript (or any technology) before adopting it is sound, and some of the arguments against TypeScript have merit. The approach, though — to masquerade opinions in a pseudo-scientific way, attaching numbers to non-quantifiable opinions, and jumping to conclusions from flawed premises — hinders having an objective discussion about TypeScript.

It is important to note that quality measures such as the code being readable and clear, well-documented, well-tested, extensible and maintainable, fall under the umbrella of qualitative quality measures. These — by definition — are hard to express in numbers, and are highly subjective.

So next, I will address some of these arguments against TypeScript, and even present some of my own. These are opinions presented as opinions. They are not facts, not metrics, not absolute truths. They are based on my personal bumpy journey with TypeScript. Read them, analyse them, question them, see what applies to your context and what doesn’t, and reach your own conclusions.

Next: The Bad and the Good reasons to reject TypeScript.

--

--