React Native and Typescript
The main intention of this blog post is to show how to setup a React Native project with a Typescript environment as an alternative to Flow.
EDIT: This guide is outdated. Please go to the updated repository: https://github.com/mrpatiwi/ReactNativeTS
Go ahead and install Node.js and the required tools from the official install guide: https://facebook.github.io/react-native/docs/getting-started.html#content
A more complete example code and starting point is available here:
ReactNativeTS - Boilerplate of a React Native project in Typescript.github.com
Up next, we will setup the most basic React Native application with Typescript.
Creating the app
Starting a React Native app is very straightforward:
# Create app
react-native init ReactNativeTS
# Navigate to the just created app
# Start git
It’s a good practice to have the Typescript-related dependencies at the package.json file, so:
npm install --save-dev typescript tslint typings
To start a Typescript project and avoid long commands on the terminal, it’s good to have a tsconfig.json file.
Also, we need to keep track of the required typings, because they are not always bundled in the dependency itself, we will use Typings:
The default config files should look like this:
Let’s find the typings of React Native. We can use the cli as follow:
typings search react-native
So, we found some typings, but they are written for DefinitelyTyped. To install them with Typings and move forward with the React typings we run:
typings install dt~react dt~react-native --save --global
The dt keyword has the meaning of telling the cli to use the definitions from DefinitelyTyped. The global flag is required for this cases.
Time to setup out tsconfig.json file. Here are declared all the required info to tell Typescript transpiler how to build our app. We will use the following settings:
- Out source code will be located at src directory and the output JS files will be placed at the build directory.
- We want to follow as much as possible the Babel import system. That’s why we will activate allowSyntheticDefaultImports.
The recommended tsconfig.json file should be like this:
Don’t forget to add the following to your .gitignore:
Prepare React Native app
To easily support Typescript, let’s create the main entrance of our app at the src directory:
As a minimal working example, our main component will be as next:
A few notes about this:
- We import React and React Native modules as always.
- Our IDE should capable of showing autocomplete for types and show warnings and errors.
- Component must have a State and Props interfaces. If empty, you can always use the any type.
- The styles must have typings.
To see how Typescript is transpiling our new components, run:
This automatically reads the tsconfig.json file.
The final JS file is placed at build/index.js:
Putting it all together
Currently, the main index files:
Are not pointing to our new base components. We should edit them as follow:
This implies that we expect to have built the TS source before running the app on a device or emulator.
Also I recommend to have the following scripts in the package.json file:
"preinstall": "rm -rf typings",
"postinstall": "node node_modules/typings/dist/bin.js install",
"start": "node node_modules/react-native/local-cli/cli.js start",
"android": "node node_modules/react-native/local-cli/cli.js run-android",
"ios": "node node_modules/react-native/local-cli/cli.js run-ios",
"prebuild": "rm -rf build",
Open two terminals and run:
# One terminal for build and watch for changes
npm run build -- --watch
# Other terminal to run the development server
iOS & Android
Open another terminal (sorry!) to run it on a iOS emulator:
npm run ios
To run it on Android, be sure to follow the install instructions from:
Now, any change made to the contents of the src directory will update the JS files. So Hot Reloading must be working well right now.
To build the source without watching is simple as:
npm run build
Adding custom components
It’s all about components and it rich ecosystem available to developers. So I will show how to add third-party modules and make them work with Typescript. Because — let’s be honest — there should be none React Native components written in Typescript with typings.
As an example, let’s take:
npm install --save react-native-button
Creating the 100% perfect typings is a hard and unnecessary work. So we can do the following:
If we use the any type, Typescript will not bother us about missing typings or wrong usage:
It’s easy and we get (rotated screen to show it better here at Medium):
It’s possible to improve the declared typings, take as example:
The usage still the same.
There are not the full typings of the components, but you can see that we can make improvements over the time.
The usage with Typescript is very simple. But it comes with risks:
- React (Facebook) has Flow. Even if it’s a annotation system, I think the invention of this has splitted the community. We could have a unique and common typings system for React and Angular. Maybe someday a combination of both of this technologies will be merged to the ECMAScript.
- It’s hard to find modules with typings. Un-official support comes with compatibility problems because of outdated or incomplete typings.
- The typings conventions are still immature, so it’s common to have errors and it’s hard to find updated information and guides.
Finally, a more complete example code is available at: