You know that application that keeps you up at night hoping you won't have to change it? It seems like we all have one.
Mine was in JavaScript. It was a single page application made with just JQuery and JavaScript and it was the most brittle thing I've ever worked with.
Let me tell you how switching to TypeScript fixed all known bugs with the application while preventing entire classes of defects from ever popping up again.
Finding Existing 'Linking' Issues
The first benefit we saw when cutting over this application was that it was immediately apparent where methods were being called with too many parameters or too little, or in the cases where method names were blatantly misspelled (this was a large and undocumented codebase without many experienced individuals working on it or standardized processes).
By forcing everything to go through tsc
(the TypeScript compiler), methods that didn't exist stopped the program flow in its tracks
Stringly-typed Variables
We had a number of variables which were being compared against numbers in some places. That's okay-ish if you're using ==
comparison where JavaScript tries to convert between stringly-typed numbers and actual numbers, but if you even tried to use ===
(which you should - for safety and for performance), you'd quickly find that '1' === 1
would be false and you'd have a lot of errors.
By declaring all of our parameters and variables with explicit types (using : number
for example), we were able to catch these issues as well.
There were a few stragglers - places where we declared the value as a number, for example, but it actually read in as a string from the user interface, but these weren't too hard to track down once we figured out what type of code to look for.
Catching silly mistakes with ESLint
We used ESLint to lint our TypeScript code since TSLint indicated at the time that it was being deprecated sometime in 2019.
ESLint allowed us to catch probable issues such as return values not being assigned to a variable or other correctness issues. Since we incorporated ESLint into our build process, this meant that any time we built we'd catch any new linting errors.
Additionally, we augmented ESLint with Prettier for code formatting, giving us a consistent code style without us having to worry about it too much.
Introducing Classes
Because we had the transpiler to catch any blatant issues and linting to catch any new goofs, we felt safe to start taking our loose JavaScript functions and move them into classes, bringing a lot more organization and standardization to our TypeScript and highlighting more opportunities for code reuse and consolidation.
Eliminating Global State
Because we introduced classes, we had to start moving state out of global scoping and into individual classes that were responsible for it.
It turned out that behind blatant method parameter mismatches and comparing values of different data types, that poor state management was the next largest cause of bugs in the application.
While we didn't have the time on this project to introduce a solution like Redux or other related frameworks, the very act of moving state into individual classes turned out to be good enough to give us the control we needed to find the improper state manipulation code and fix it.
Testability
Taking a large nest of spaghetti JavaScript and chopping it up into TypeScript classes also allowed us to write Jest tests around individual classes, giving us a further degree of safety and confidence while making changes to the application.
Ultimately, migrating an old legacy JavaScript application to TypeScript turned out to be a fantastic move for development, quality assurance, and the end users because the additional rigor and safety measures we introduced stabilized the application to the point where we could make changes without breaking things.
Sure, I didn't get to convert the application to Angular or add a state management framework like Redux, but at the end of the day, the project finished early and without defects and resolved a large number of existing defects in the process - to the point of it being faster to move the application to TypeScript than to hunt down each individual bug in JavaScript and fix it, hoping we caught all aspects of it.
Every project is different, but I strongly recommend you consider TypeScript if you need to bring order and quality to an aging application.