Toxic flexibility - a case for TypeScript
Tags: typescript, javascript, codequality
Published: 2021-07-31 14:39:29

## Which option would you take?

* Spend medium amount of time in rare exotic edge cases but also in the majority of the cases (`vanilla JS`)
* Spend a lot less time in the majority of cases but a lot more development time in rare and exotic cases (`TypeScript`)

I will give you my answer at the end of this article, but now let's see a needlessly complicated JS example:

```javascript
let thing = {
  sushi: '🍣',
  doThangStuff() {
    return thang.stuff.a;
  },
  thisWillBeBound() {
    console.log('Sushi:', this.sushi);
  },
};

let thang = {
  stuff: {
    a: 123,
    b: thing,
  },
  callThing() {
    thing.thisWillBeBound = thing.thisWillBeBound.bind(Object.assign(this, { sushi: 'sushi' }));
    thing.thisWillBeBound();
  },
  doMagic() {
    console.log(this.aPropertyAddedLater + ['55']);
  },
};

thang.aPropertyAddedLater = 123;
thang.doMagic();

thing.thisWillBeBound(); // Sushi: 🍣
thang.callThing(); // Sushi: sushi
thing.thisWillBeBound(); // Sushi: sushi

function renameFunction(fn, name) {
 Object.defineProperty(fn, 'name', { value: name });
}

renameFunction(thang.doMagic, 'doUnicornStuff');
console.log(thang.doMagic.name); // doUnicornStuff
```

I know it's a lot, you don't need to fully understand it, but the point is: everything here is valid JS code. The flexibility of the language is allowing all this and more.

This is really-really _useful_ when you are writing a throwaway script (originally intended design of the language) and you do not want to write pages of code. This is however _counterproductive_ when you have hundreds of files in a large project.

### Who would write this convoluted code?
Well, `renameFunction` was already coming from a project I took over, so some of it is in the wild already, but in most cases nobody would write it. That's one thing.

The other one is that tooling (your IDE, the engine running code, the code linters, code coverage tools etc.) must work with the language as it is with all its options.

> So yes, nobody writes code like this, but no, the tooling cannot _trust_ the language not to be like this.

## Toxic flexibility
Let me define it:

> **Toxic flexibility** of a programming language is when allowing a large number of exotic edge cases hurt the coding experience of the majority of the cases.

...rendering it impossible to have **useful tooling** built around the language.

Simple example, before ES5 you could even overwrite `undefined` 😱. ([This option got removed](https://stackoverflow.com/a/8783528) and no-one cried about backward compatibility).

On one end you have complete `trust` in your code resulting from strict, statically computable rules, yielding that at any given line in your code you are sure what are the possible values. 

> And on the other end: **toxic flexibility**. You only have _probability_ arising from coding conventions, developer taste, usage stats...

I.e. the IDE can only say: _"I think most likely you wish to access one of these possible properties of this object, function or primitive, I don't know, don't get angry at me if it's wrong!"_.

_Fun fact:_ One of my former colleagues in 2017 decided he wanted to do `JS` to stay relevant after doing mostly `MSSQL` and `C#`. Whenever *WebStorm* code completion feature suggested a property he would press `Enter` and get on with it. Later he called us because he was confused _"Why is everything damn `undefined`?"_. We giggled and told him, _"Man, that list is gibberish, don't even look at it!"_. At that time I already knew the pain for 2 straight years.

## The reason behind the creation of TypeScript
No, it was not enforcing the dated `Object oriented principle` on this beautifully flexible and functional language (irony). It was created for increasing `trust` in the code the **tooling** was working with. Let me quote [Anders Hjelsberg, co-creator of TypeScript](https://www.zdnet.com/article/typescript-creator-how-the-programming-language-beat-microsofts-open-source-fears/):

> All the _programmer productivity features_ we have like VSCode's **IntelliSense**, **code definition** and **code navigation** require the **IDE** _to be able to reason about the code_ that you're working on.

> A **type system** is one way you can _reason about your code_. It's the ability to check your code before you run and deploy it. Without types in a language that's almost impossible.

So by adding type information and understanding how that information changes from line-to-line gave us better tooling, living documentation and quicker development times.

If you have ever tried a strongly-typed language with a good IDE (like **Visual Studio** and **C#**) you know how it can give you for every line the suggestions just you need, you only need one letter from it basically.

### Working for the majority of cases
As I wrote above: the tooling of `JS` cannot really help you, since you have to **run** the code to actually know what it is really doing. In that case the very rare edge cases of the flexibility of the language forbid any smarter static analysis of the code.

By adding code with proper types you are reducing the **number of cases** you can have in a given line of code. Inferring the rest from primitive types (we are mostly dealing with `phoneNumber`s and `email`s and `score`s, `string`s and `number`s...)  and solid coding `TypeScript` compiler does the heavy lifting for you.

To give you my answer to the question at the start: I prefer **code completion** and **static refactoring help** in every line I write over the flexibility of vanilla `JS`. 

> The "silence" of coding tools makes me check the functions I call, searching for signs of what they'd return, write me tests I would not need and makes me nervous with simple everyday tasks, like renaming a function.

These are everyday scenarios and it _is_ **time lost**. With `TypeScript` these are usually covered by the tooling so I need to think more about what my code actually should do over making sure it is really getting and emitting the correct data.

Using `TypeScript` has also drawbacks of course. Writing exotic, very dynamic code and typing it properly will take a lot more time than in vanilla `JS`.

But I would rather pay this price than not having the tooling that works for me.

## Conclusion
Strict typing might be just one particular solution to lower **toxic flexibility** to the point that meaningful help can be provided by our tooling. If you have a disdain for it - or with `TypeScript` in concretion - you can still embark on your own journey on figuring out novel methods to know more about the code before you are running it.