Skip to content

Instantly share code, notes, and snippets.

@cuibonobo
Last active May 29, 2018 16:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cuibonobo/662e79776469de53f2dd08f35626b086 to your computer and use it in GitHub Desktop.
Save cuibonobo/662e79776469de53f2dd08f35626b086 to your computer and use it in GitHub Desktop.
How to create a TypeScript-enabled React Native starter app without relying on cloning boilerplates or example projects.

React Native Typescript App

Make sure you have some global CLI tools installed:

npm install -g typescript create-react-native-app

You may also want to update npm to the latest version:

npm install -g npm

A lot of the information for this README was taken from https://github.com/Microsoft/TypeScript-React-Native-Starter, but there were some small changes in order to reflect a workflow using create-react-native-app.

Creating a React Native app

create-react-native-app my-app
cd my-app/

I recommend creating an Expo account, downloading the Expo XDE desktop client, and getting the Expo Android or iOS app in order to quickly prototype the app on a real device.

Initialize TypeScript and install types

tsc --init --pretty --jsx react
npm install --save-dev @types/react @types/react-native
npm install --save tslib

Install TypeScript transformer

The React Native packager can be configured to kick off TypeScript builds behind the scenes by installing a transformer:

npm install --save-dev react-native-typescript-transformer typescript

Now configure the packager to use the TypeScript transformer when files with a ts or tsx extension are touched. Edit the app.json file to look like this:

{
  "expo": {
    "sdkVersion": "27.0.0",
    "packagerOpts": {
      "sourceExts": ["ts", "tsx"],
      "transformer": "node_modules/react-native-typescript-transformer/index.js"
    }
  }
}

Configure TypeScript for the project

Edit the tsconfig.json file to enable the following settings:

{
  "compilerOptions": {
    "target": "es2015",
    "module": "es2015",
    "allowJs": true,
    "jsx": "react",
    "sourceMap": true,
    "importHelpers": true,
    "strict": true,
    "noImplicitAny": true,
    "strictNullChecks": true,
    "noImplicitThis": true,
    "noUnusedLocals": true,
    "noImplicitReturns": true,
    "moduleResolution": "node",
    "allowSyntheticDefaultImports": true,
    "esModuleInterop": true,
    "preserveConstEnums": true,
    "forceConsistentCasingInFileNames": true,
    "suppressImplicitAnyIndexErrors": true,
    "skipLibCheck": true,
    "noEmit": true,
    "noEmitHelpers": true
  },
  "exclude": [
    "App.js",
    "App.test.js",
    "build",
    "node_modules"
  ],
  "compileOnSave": false
}

Create an AppRoot.tsx file and build it

Create a src/AppRoot.tsx file with the following content:

import React from 'react'
import { Component } from 'react';
import {
  Platform,
  StyleSheet,
  Text,
  View
} from 'react-native';

const instructions = Platform.select({
  ios: 'Press Cmd+R to reload,\n' +
    'Cmd+D or shake for dev menu',
  android: 'Double tap R on your keyboard to reload,\n' +
    'Shake or press menu button for dev menu',
});


type Props = {};
export default class App extends Component<Props> {
  render() {
    return (
      <View style={styles.container}>
        <Text style={styles.welcome}>
          Welcome to React Native!
        </Text>
        <Text style={styles.instructions}>
          To get started, edit src/AppRoot.tsx
        </Text>
        <Text style={styles.instructions}>
          {instructions}
        </Text>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#F5FCFF',
  },
  welcome: {
    fontSize: 20,
    textAlign: 'center',
    margin: 10,
  },
  instructions: {
    textAlign: 'center',
    color: '#333333',
    marginBottom: 5,
  },
});

Replace the App.js content

We want to use our TypeScript source files instead of the React Native defaults, so replace the content of App.js with the following:

import App from './src/AppRoot'

export default App;

Test in Expo

Open the project in Expo XDE and click 'Share' to send a link to the project to your email address or scan a QR code. You can also run the project from the command line with npm start. Opening the link or scanning the QR code with your mobile device will automatically open the Expo mobile app.

Once the app loads, you should see a view of your app that says, "Welcome to React Native!".

Configure testing

To prepare the app for TypeScript-enabled testing, run the following:

npm install --save-dev react-test-renderer ts-jest @types/jest @types/react-test-renderer

Edit the jest key in package.json to look like this:

{
  "preset": "jest-expo",
  "moduleFileExtensions": [
    "ts",
    "tsx",
    "js"
  ],
  "transform": {
    "^.+\\.(js)$": "<rootDir>/node_modules/babel-jest",
    "\\.(ts|tsx)$": "<rootDir>/node_modules/ts-jest/preprocessor.js"
  },
  "testRegex": "(/__tests__/.*|\\.(test|spec))\\.(ts|tsx|js)$",
  "testPathIgnorePatterns": [
    "\\.snap$",
    "<rootDir>/node_modules/"
  ],
  "cacheDirectory": ".jest/cache"
}

Edit App.test.js so that the App import comes from the TypeScript source:

import App from './src/AppRoot';

Run tests and make sure that they pass:

npm test

Add auto-generated files to .gitignore

Add the following to your .gitignore file so auto-generated files aren't added to source control:

build/
.jest/
@cuibonobo
Copy link
Author

Add auto-generated documentation by installing TypeDoc (npm install --save-dev typedoc) and adding the following to tsconfig.json:

  "typedocOptions": {
    "name": "My App",
    "out": "build/docs",
    "includes": "docs",
    "excludePrivate": true,
    "excludeNotExported": true,
    "excludeExternals": true,
    "includeDeclarations": true
  }

You can now generate docs by running npx typedoc src. The documentation will scan the src directory for source files and save the generated documentation at build/docs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment