From ESLint to TSLint and Back Again
TypeScript + ESlint examples of Node.js, React Web, and React Native.

History
Go back several years and many of us were writing JavaScript; linting our code with ESLint, Airbnb rules, and Prettier.
When we switched to TypeScript, we were forced to switch to TSLint (and their base rules) and Prettier.
Now that TSLint is being deprecated in favor of a collaborative solution with ESLint (typescript-eslint), we are switching back to ESLint, Airbnb rules, and Prettier.
If it was only that simple…
Through three concrete examples (Node.js, React Web, and React Native), we explore the details of using the typescript-eslint solution.
Prerequisites
To follow along, one will need to have the latest Node.js LTS version installed; this article was written with version 10.16.1.
To make the most of linting, use a capable editor, like Visual Studio Code, that supports ESLint and Prettier; for VSCode this requires the appropriate extensions.
Node.js Example
The completed Node.js example is available for download.
We need to first scaffold a basic Node.js + TypeScript project without linting. One such solution is documented in Tech Stack 2019: Core; skipping the installation of anything starting with tslint, the tslint.json file, and replacing the entries with tslint in package.json with a placeholder, e.g.:
echo \"Success: no lint configuration\" && exit 0
If not already done previously, install and configure Prettier:
npm install --dev prettier
with a Prettier configuration, e.g.; .prettierrc:
We then install eslint-config-airbnb-base with its peer dependencies:
npx install-peerdeps --dev eslint-config-airbnb-base
note: eslint-config-airbnb-base has a peer dependency with an older, ^5.3.0, version of eslint; having a major version release in late June 2019.
We then install the remaining dependencies:
npm install --dev eslint-config-prettier
npm install --dev eslint-plugin-prettier
npm install --dev @typescript-eslint/parser
npm install --dev @typescript-eslint/eslint-plugin
The next bit of complexity is creating the ESLint configuration file supporting these dependencies. Following the documentation provided by @typescript-eslint/eslint-plugin, with a couple of minor tweaks, we end up with the following .eslintrc:
Observations:
- The settings section is required as eslint-plugin-import does not currently recognize TypeScript extensions
Finally, we update package.json with the eslint command:
React Web Example
The complete React Web example is available for download.
Scaffolding a React Web + TypeScript project is simple:
npx create-react-app eslint-react-web --typescript
note: If one has Yarn installed on one’s machine, CRA defaults to using Yarn instead of npm; these instructions use Yarn.
First we install and configure Prettier:
yarn add prettier --dev
with a Prettier configuration, e.g.; .prettierrc:
We then install eslint-config-airbnb with its peer dependencies:
npx install-peerdeps --dev eslint-config-airbnb
note: This command will actually prompt for the appropriate Node.js package manager; in this case Yarn.
Addendum 12/5/19: Feel like I am playing a game of “whack-a-mole”, but now, Create React App is using eslint 6.6.0 and complains about the install of eslint 6.6.1 (because of eslint-config-airbnb). Solution here is to delete package/yarn lock file, node_modules, remove eslint from package.json and install:
yarn add eslint@6.6.0 --dev
We then install the remaining dependencies:
yarn add eslint-config-prettier --dev
yarn add eslint-plugin-prettier --dev
yarn add @typescript-eslint/parser --dev
yarn add @typescript-eslint/eslint-plugin --dev
yarn add eslint-plugin-jest --dev
note: As React Web ships with Jest (testing framework), we added the appropriate plugin.
As with the Node.js example, the next bit of complexity is creating the ESLint configuration file supporting these dependencies. Following the documentation provided by @typescript-eslint/eslint-plugin, with a couple of minor tweaks, we end up with the following .eslintrc:
Observations:
- As with the Node.js example, the settings section is required as eslint-plugin-import does not currently recognize TypeScript extensions
- As eslint-plugin-react does not recognize the TypeScript JSX extension, we add a rule to support it
- The spaced-comment rule is updated to support the TypeScript Triple-Slash Directive
Finally, we update package.json with the eslint command; checks both .ts and .tsx files:
Observations:
- When editing package.json, one might be tempted to change the eslintConfig property; apparently doing so has no effect
As the new linting configuration is much stricter than React’s supplied one, running the new linter configuration:
yarn lint
turns up 159 problems that we need to resolve.
Hints:
- Since src/serviceWorker.ts is not a file one is expected to edit and most of the errors are in it; the easy-button here is to simply disable linting in it
Addendum 12/15/19: Assuming that you plan on using React hooks, it is recommended that you install the eslint plugin that checks the rules of hooks, see React-Rules of Hooks.
React Native Example
Addendum October 16, 2019: Looks like in the last month or so, the React Native installation processed changed.
Currently, only way to get React Native to install was with:
npx react-native init [PROJECT NAME]
and then follow the instructions to add TypeScript to an existing project.
Then a couple of things changed:
- React Native ships with a .prettierrc.js file that conflicts with some of the linting rules; replaced with the .prettierrc file below
- React Native ships with the .eslint.js file; replaced with .eslintrc file below
First we install and configure Prettier:
yarn add prettier --dev
with a Prettier configuration, e.g.; .prettierrc:
We then install eslint-config-airbnb with its peer dependencies:
npx install-peerdeps --dev eslint-config-airbnb
note: This command will actually prompt for the appropriate Node.js package manager; in this case Yarn.
note: Unlike React Web, the React Native build process does not include a linting step.
We then install the remaining dependencies:
yarn add eslint-config-prettier --dev
yarn add eslint-plugin-prettier --dev
yarn add @typescript-eslint/parser --dev
yarn add @typescript-eslint/eslint-plugin --dev
yarn add eslint-plugin-jest --dev
yarn add eslint-plugin-react-native --dev
note: As React Native ships with Jest (testing framework), we added the appropriate plugin.
note: We also added eslint-plugin-react-native to support React Native.
As with the previous examples, the next bit of complexity is creating the ESLint configuration file supporting these dependencies. We use a similar configuration as React Web:
Observations:
- Starting from the React Web’s configuration, we replace React Web’s browser env with react-native/react-native and add the react-native plugin
Finally, we update package.json with the eslint command:
Observations:
- As we are only linting files in the src folder, we move App.tsx and associated __tests__ folder to it
As the new linting configuration is much stricter than React Native’s supplied one, running the new linter configuration:
yarn lint
turns up 27 problems that we need to resolve.
Finally, looks like the React Native TypeScript configuration neglects to define the React Native global object; we can correct it by supplying a declaration file; src/types/global.d.ts:
Addendum 12/15/19: Assuming that you plan on using React hooks, it is recommended that you install the eslint plugin that checks the rules of hooks, see React-Rules of Hooks.
Wrap Up
Wow. This was a bit harder than I expected. Hope you find it useful.
- eslint-config-airbnb now works with eslint 6.1.0