Learnings from migrating Atlaskit to TypeScript

This blog is aimed at people who are considering migrating their large projects to TypeScript!
So TypeScript support has recently landed in Atlaskit š and what a journey it was! I think now is a good time to reflect on what I found worked and what I would do if I was to do it all over again.
Full disclosure: It was a large and challenging undertakingā¦ but one I would encourage regardless
Our project
In the spirit of transparency, Iād like to share some rough resource numbers, to give you an idea of what you might be in for.
We had roughly ~10 different engineers working on the project over its lifespan. At the start, we had 5 people working on it full-time. This is where we made most of our progress. But as time went on, naturally people were pulled into other, more important initiatives and so about halfway through and we dropped back to 1 to 2 full-time engineers at best, for the remainder of the project.
Itās important to note that we were also juggling other priorities such as support, bugs, other projects, etc.
The whole effort spanned ~6 months all up.
Tip #1: Automate everything š¤
I canāt stress this enough, use or build your own automation to do the tedious bits. Youāll likely never get something that converts perfectly, but you can get most of the way there.
This worked for us: alexreardon/sink
It automated:
- Transformed our already type-safe flow code and converted whatever syntax it could into TypeScript
- It renamed files from
.js
to.ts
&.tsx
(surprisingly tedious) - Added TS specific configuration files
- Removed old configuration files
Sink is highly Atlaskit specific, but consider taking a similar approach. You wont regret it š!
In hindsight I wish we invested more time in automating our conversion. If I was to do it again today, I would definitely investigate an AST based approach.
But still definitely worth the upfront effort!
Tip #2: Do not refactor AND convert to TypeScript š„
It is really tempting to refactor code as you go, but you must resist the urge to clean up code while youāre migrating at all costs!
When youāre migrating youāll look at every line of code critically. Youāre bound to find things that bother you. But itās important to resist because the risk of introducing a regression is extremely high and there is a strong chance that you or your PR reviewers will miss issues. Think about it, youāre touching a lot of files, your PR diff is already cluttered with deltas, and then introducing logic changes on top of that ā A recipe for disasterš„.
Trust me on this one š
Just focus on moving from one working state to the next. If you need to refactor your component it should be a separate activity all together. Make a note or Jira ticket somewhere, do it later.
Tip #3: Enable allowJs š²
allowjs: Allow JavaScript files to be compiled.
If your codebase is big, do yourself a favor and enable allowJs so you can progressively convert components file-by-file, instead of doing an entire component at a time, which is what we did š. I found that it blew-out the size of the PRs and made getting past CI a real pain in the butt š.
Tip #4: Capture the Gotchas š
Keep a list of rules / best practices to govern the team. There are lots of little scenarios that happen over and over such as:
Which event handler do I use for this prop? How do i type HOCs? When should I use an interface over a type? Should I export my props?
Form these opinions as a team, share all the resources, discuss together and document it for later.
Here are some resources we usedā¦
Absolute god-send: typescript-cheatsheets/react
You might also find these useful:
- piotrwitek/react-redux-typescript-guide
- TypeScript Styleguide
- microsoft/TypeScript-Handbook
- Ultimate React Component Patterns with Typescript 2.8
Tip #5: Go upwards from the leaf nodes š
This should be a no-brainer: Start with the most simple and dependency-free components you have and move up and up the tree until youāre finished.
Tip #6: Beware the HOC š²
In our conversion the most challenging obstacle to overcome, by far, was successfully typing a HOC (higher order component). Handle these with the most care, because itās possible that the return type of a HOC can be incorrectly typed.
Itās worth noting here that HOCs come in different flavors and the way you approach typing them varies slightly. If you get stuck check out these guides:
Closing thoughts š
Donāt let this blog discourage you, it was totally worth every second of the effort in my eyes. We found countless bugs in the process, we learned a lot about the quality of our components and in general feel like weāre walking away with an a lot more stable codebase!