Convert a React Native Project to TypeScript in 10 Minutes
Alex Hinson presented the following as a Lightning Talk at the 2019 Chain React conference, which was incredible, on July 11.
Hey everyone! Thanks for coming out today. I’m Alex and I’m a developer at a great company called Airship based in Birmingham, Alabama.
I want to first start off on a more personal note by saying how thankful I am to be here today. I’ve attended Chain React for the past 2 years, and I am completely honored to be able to present this year. Over the course of those 2 years, a lot has changed in the React & React Native community, particularly regarding TypeScript. As I’m sure everyone in this room can attest to, it has been virtually impossible to browse twitter or blogs and NOT see people talking about switching to TypeScript. You’ve probably seen things like this:
- Even Infinite Red is on the TypeScript hype train!
What is TypeScript
Throughout the process today, we’ll use an existing project of mine, which may be a bit arbitrarily simple, yet… strangely important? :), but nonetheless this project will help convey the ideas involved in each part of the conversion.
One of the great things about TypeScript is that it is very configurable, so we can make it as strict or loose as we want, in terms of type-checking. A common problem I’ve seen is when people try converting projects over to TypeScript all in one go with a strict configuration, so the initial setup is way more effort than it should be. That’s why we’re splitting it up into 3 particular steps.
Each of these 3 steps could be the “end” of your conversation to TS, and you’ll get a certain level of benefits from each.
We will go from the loosest configuration to the strictest, and you can make your own judgements about what level makes sense for you and your team.
Step 1: rename js to ts / implicit any
And on to step 1! Just Make It Work
Our goal for this first step will simply be to get our code running again without having to make any significant changes to the code itself. We will need to setup a basic config file so that TypeScript can know the particular rules we want it to follow or not follow. As I mentioned before, this will be the loosest configuration of TypeScript.
Here is an example of a standard tsconfig file for React Native, which will live in the root of the project. It has a couple of rules that we’re going to gloss over for the sake of time, but I want to focus on one in particular. Setting
false will allow implicit anys. These implicit anys are used in TypeScript when it cannot infer a particular type of a variable. We’re allowing these in this first step just to get our project to compile with TypeScript without making any significant changes to the code.
If you have a larger project that isn’t just a two screen app about cats, manually changing these over could be a bit time consuming, but luckily, there’s an excellent appropriately titled tool called js-to-ts-converter that handles changing all the file extensions over as well as parsing the file for any JSX and naming the file with a .tsx extension in that case.
Once we’re done changing the file extensions over, we’re now working with a TypeScript project! However, there’s a decent possibility that we might still see a few errors, which is actually a good thing!
You can see in the example here that I have a logError function at the top that expects 2 arguments, however when I’m using that function below, I’m only passing it one, and TypeScript brought it to my attention immediately and tells me what argument I’m missing.
Once I fix those issues, the project should run successfully, and we’re officially done with step 1!
Step 2: explicit any
Now for step 2 – Be Explicit!
The next step in the process will be to only allow explicit anys, by simply toggling
true. This means that instead of TypeScript defaulting to an ‘any’ type when it can’t use type inference, it will actually give a compile error. All of the places that the compiler was automatically adding an any type will now require you to give it a type or explicitly say it is an any.
You can see here that I’m saying that this function expects an image ID as a string and a value as a boolean.
I would then need to go through all areas of my application and do this same sort of thing
This is also the time to start creating the common object types that are used throughout the project and adding them where possible.
Here is a Cat object type, and you can see it all the properties that it has. I’ll then use this type all over my project anytime I’m dealing with a Cat in the data.
@types before the library name and add it to your project’s dev dependencies.
This step will probably take just a bit longer than the 1st step, but the efforts you spend will pay off dividends once you start adding to your codebase, and especially when you start refactoring.
Like I mentioned before, any of these steps can be the “end” of your TypeScript conversion. We have many projects at Airship that ended up somewhere in the middle of steps 1 and 2, and they are much better off because of it.
However, if you want to keep pushing on and go all in on TypeScript to get the full benefit, there’s only one more step!
Step 3: Strict mode
And we’ll call it Strict Mode!
For example, one of the rules enabled with the “strict” setting is “strictNullChecks”. This was created to help ensure that you don’t try to access a particular property of an object, for instance, that could potentially be null or undefined.
For example, we have this Cat type from earlier and it has an optional property age. You can see that it is optional because it has a question mark after the key, which means that it could be undefined. When I try to run the toString method on age, TypeScript will give me an error, so I’ll need to make sure age exists first before trying to run the method, otherwise I’ll just return a default string.
Review / Conclusion
First we added a basic TypeScript configuration and simply changed the file extensions. Then we got more explicit about the types we are using throughout the application by turning off implicit anys and creating our own common types as well as bring in 3rd party types. And finally we enabled the strict configuration, which further ensures that we’re writing safe and error-resilient code.
Now, I know the title of this lightning talk might have been a bit misleading, because a full & complete conversion to TypeScript with a robust project that isn’t a two screen app about cats could take days or weeks or even months, but I want to reiterate the fact that TypeScript can add value to any project, whether it’s just at step one or 100% integrated.
I hope this quick talk helped clear up some questions you might have had, but there are also many details that we weren’t able to get to today, so please come find me afterwards if you’d like to chat any further about TypeScript and React Native.
To learn more about Alex’s other React Native speaking events across the globe, check out this page. To read more about Alex, check out his bio!
Photo courtesy of the talented @SteveSaul82 (tweet embedded in article above)