Hello Create React App (CRA) - TypeScript

John Tucker
codeburst
Published in
4 min readDec 6, 2018

--

Taking CRA TypeScript support out for a spin.

As of the October 2018, 2.1.0 release, CRA introduced TypeScript support. While I have always managed a custom-built build solution (i.e., webpack configuration), I have, more recently, been exploring using CRA and thought to give its TypeScript support for a spin.

note: This article is not about customizing the CRA build itself, i.e., ejecting, monkey-patching with customize-cra, or forking react-script.

If you wish to follow along, you will need to have a relatively recent version of Node.js installed; this article was written with 10.14.0.

The final solution from this article is available for download.

Just the Basics

We first scaffold the project:

npx create-react-app hello-cra-ts --typescript

Polyfills

We now add in the standard CRA solution for polyfills; specifically for support in IE 11.

yarn add react-app-polyfill

and update src / index.tsx:

import 'react-app-polyfill/ie11';
...

Linting

The first observation is that unlike JavaScript, TypeScript itself does a considerable amount of code-quality checks before a linter is even introduced.

Because CRA does not expose its linting configurations, we will want to setup linting configurations for the project to enable linting our editor.

note: This assumes that one is using an editor that supports linting, e.g., VS Code with the TSLint, and Prettier — Code Formatter extensions; highly recommended.

Linting — TypeScript

It is unclear if CRA provides any TypeScript linting; it appears to only rely on TypeScript compiler errors. We will go ahead and install the recommended TSLint configuration with Prettier.

We first install the dependencies:

yarn add --dev tslint
yarn add --dev prettier
yarn add --dev tslint-config-prettier
yarn add --dev tslint-plugin-prettier
yarn add --dev tslint-react

We create the Prettier configuration; .prettierrc

We then create the TSLint configuration file; tslint.json:

Finally, we create a lint-ts script in package.json:

{
...
"scripts": {
...
"lint-ts": "tslint -c tslint.json 'src/**/*.{ts,tsx}'",
...
},
...
}

With this script in place, we can lint out project with:

yarn lint-ts

With this in place, we know that it is working as we find a number of errors (and correct them):

  • src/serviceWorker.ts: Just put a TSLint ignore at top
  • src/index.tsx: As need polyfill at top, disabled first error about import ordering; reordered the other imports
  • src/App.tsx: Updated order of imports and added public to render method

Husky and lint-staged

In order to lint before committing and pushing changes, we add Husky and lint-staged.

yarn add --dev husky
yarn add --dev lint-staged

and update package.json:

...
"husky": {
"hooks": {
"pre-commit": "export CI=true && yarn build && lint-staged && yarn test",
"pre-push": "export CI=true && yarn build && lint-staged && yarn test"
}
},
"lint-staged": {
"*.{ts,tsx}": ["tslint -c tslint.json"]
}
...

Wrap Up

We can see that CRA with TypeScript support (with an extra bit of project configuration) gives use a pretty solid build solution. Some of the things that it handles in TypeScript seamlessly under the hood are:

  • Media
  • Styling, including SASS support (you have to add peer dependency) and CSS Modules
  • Tree Shaking / Source Maps / Minification / Caching
  • Code Splitting
  • Environment Variables

Linting — JavaScript (Optional)

While Create React App supports both TypeScript and JavaScript in the same project, I have lately only been writing TypeScript; thus making this section optional (and not included in the final example).

note: This assumes that one is using an editor that supports linting, e.g., VS Code with the ESLint extension; highly recommended.

For JavaScript, we observe that the built-in linting configuration is lax and that we likely want to use the more strict eslint-config-airbnb (syntax) and Prettier (formatting) configuration.

We first install the dependencies (yes, there are a few):

yarn add --dev eslint
yarn add --dev babel-eslint
yarn add --dev eslint-plugin-import
yarn add --dev eslint-plugin-jsx-a11y
yarn add --dev eslint-plugin-react
yarn add --dev eslint-config-airbnb
yarn add --dev eslint-plugin-prettier
yarn add --dev eslint-config-prettier
yarn add --dev eslint-plugin-jest

note: We presumably already installed Prettier and its configuration file.

We then create the ESLint configuration file; .eslintrc:

Next we add a file to allow our linting configuration to coexist with CRA; .env

Finally, we create a lint-js script and update lint-staged in package.json:

{
...
"scripts": {
...
"lint-js": "eslint 'src/**/*.{js,jsx}'",
...
},
...
"lint-staged": {
...
"*.{js,jsx}": ["eslint"]
}
}

With this script in place, we can lint out project (likely used with a continuous integration solution) with:

yarn lint-js

--

--