TypeScript forced us to document all of our assortment of feature flags and switches. We have a lot of flags for various features, and by using interfaces we can no longer have mysterious undocumented flags. All flags must be in the interface or else the compiler will warn us. This keeps developers honest.
Keep reading to learn more about this journey.
Why We Rewrote It
From improving our build infrastructure to giving us guarantees thanks to its types, these are the problems we had and TypeScript helped us fix:
- Maintaining the Almond.js compiler infrastructure was cumbersome. Different builds meant different files and different tests. We also had to write a lot of plain text on those files. That text was later evaluated to be bundled as JS due to the AMD module system.
- Keeping 3rd-party libraries up to date was a manual process. Now we use package.json and simply import the libraries using an import statement. In the past, we were directly pulling 3rd-party files from our local repository to bundle them into the snippet, if we wanted to update a library we needed to update the file by hand. Now we run `yarn upgrade` and we are ready to go!
- We needed to improve our old browser support and have guarantees around it. TypeScript has a compiler flag that lets us target older browsers. Thus we can guarantee to our customers that our SDK works in ES3 and up browsers.
- Several bugs that had been in the original code for a while:
- The compiler found a function that was supposed to return a boolean but wasn’t returning anything. We were using this function in an if statement and the compiler warned us that the function wasn’t returning a boolean.
- By using interfaces we discovered that our configuration contained a duplicate configuration object inside of it. Using recursive interfaces we were able to define this unusual property.
- After adding type signatures to our internal priority queue, the compiler told us that some of our functions had return value mismatches. Some parts of our code were expecting Promises and weren’t getting them. This led us to discover a serious bug in the code.
You can't just pick new languages and force them into your stack. You have to measure the trade-offs and take a look at the pros and cons that the new tool will bring. In our TypeScript projects these are the results and we think the trade-offs are worth it.
- TypeScript forced us to document all of our assortment of feature flags and switches. We have a lot of flags for various features, and by using interfaces we can no longer have mysterious undocumented flags. All flags must be in the interface or else the compiler will warn us. This keeps developers honest.
- Increased maintainability because the SDK was getting large enough that making big changes was very scary and we might cause regressions. Having everything typed, we can refactor with more confidence.
- Not having to write semicolons is hard at first but after a while, you wonder why you had to write them in the first place.
- @types is mature now, and every library we needed had types registered with Definitely Typed.
- Often overlooked and underestimated, having a code base that makes your job easier and more fun is a win for the engineering team. TypeScript has excellent tooling and we are very happy about that.
- The build time has gotten slower but we’re starting to fix that using guides like this one.
- Developers need to ramp up with a whole new language, tool-chain, and conventions.