Reviving a Legacy TypeScript Application

Recently I came across a project written in TypeScript that was established in 2014. That’s was only 2 years after the creation of TypeScript, and much, much before it’s increase in popularity. And as such, the project was starting to show it’s age.

Some Background

When the project began, much of the amazing open source tooling and configurations for TypeScript didn’t exist yet. That includes a much improved TypeScript core, and a much more robust set of rules for TSLint, that includes tslint-recommended and tslint-prettier-config.

After upgrading the TypeScript dependency and adding these new configurations, I found that this (pretty large application) had over 50k lint/compiler errors.

Pretty daunting. But hey, that’s half the fun.

TypeScript made some things easy

About 95% of these errors were due to prettier’s opinionated approach to spacing, and line lengths — these errors fixed themselves by running our lint command with the --fix argument.

But that still left about about 2500 actual errors.

Some of these issues were actually hard to find/reproduce bugs. And we were able to fix these in a fairly straightforward way.

However, for many (I’d say about ~250), we took the safest approach, by adding some tslint-ignore comments where it made sense.

So what didn’t TypeScript make easy?

I was extremely surprised to find that TSLint didn’t auto-fix uses of var to the preferred const and let keywords. More than that, I was downright annoyed.

TSLint would throw errors during lint, but the --fix command provided no help. And we didn’t want to go and add ignore comments, or fix hundreds of variable declaration.

So instead, we used a little bash to change all of our var declarations to let:

find -name "*.ts"  -exec sed -ie "s/var/let/" {} \;

Which transforms this code:


var thing = 1;
var thing2 = 2;
thing2 += thing1;

into

let thing = 1;
let thing2 = 2
thing2 += thing1;

and from there we could simply tun tslint -- --fix which turned our code into:

const thing = 1;
let thing2 = 2
thing2 += thing1;

and voila, all 50k errors in our application have been fixed.

Conclusion

For me, the power in doing this kind of work is less about fixing old issues, especially in applications that serve a business need. The true power in making these fixes is in enabling better code to be written in the future. Sure, we did fix some bugs, but more importantly, we’re also going to stop letting future bugs be written.