Note: CRA 3.0 will include TS linting with ESLint out of the box, https://github.com/facebook/create-react-app/issues/6475
I recently learned that TSLint was soon to be deprecated (cue sad violin music), but for very good reason as the JS/TS community starts to converge around a common set of core technologies. If you're interested in learning about these reason Palantir (creator of TSLint) has a nice read for you over here.
Alas the time had come for me to switch my small personal project to TypeScript. I've been a full time TypeScript dev for the past year and found that I miss it dearly even on smaller JavaScript projects. I used to opt for plain old JS to reduce complexity, but at this point my knowledge of TypeScript makes it fairly effortless to configure on even the simplest projects. Not to mention that the latest version of Create React App support TypeScript integration right out of the box!
I've set up TSLint quite a few times in the past, but knowing that ESLint was the future of TypeScript linting I decided to give it a go. Set up wasn't as straight forward as I would've hoped given that things are in quite a state of flux at the moment presented some challenges due to lack of documentation so I've decided to document here.
This article assumes you're using the latest version of CRA which comes with ESLint already out of the box.
First, let's install or devDependencies
npm i -D @types/react @typescript-eslint/eslint-plugin @typescript-eslint/parser eslint-config-prettier eslint-config-react eslint-plugin-prettier prettier
Your devDependecies in package.json should now look like this,
"devDependencies": {
"@typescript-eslint/eslint-plugin": "^1.6.0",
"@typescript-eslint/parser": "^1.6.0",
"eslint-config-prettier": "^4.1.0",
"eslint-config-react": "^1.1.7",
"eslint-plugin-prettier": "^3.0.1",
"prettier": "^1.16.4"
}
Now create two files in your projects root (same level as your src folder).
.eslintignore
.eslintrc.json
You might see some tutorials use .yml
or .js
configurations and some tutorials might exclude an .eslintignore
all together and use pattern matching in their node js scripts to exclude certain folders. All of these approaches are valid and it's really a matter of preference which one you decide to use.
In your .eslintrc.json add
{
"extends": [
"eslint:recommended",
"plugin:react/recommended",
"plugin:@typescript-eslint/recommended",
"prettier/@typescript-eslint",
"plugin:prettier/recommended"
],
"plugins": ["react", "@typescript-eslint", "prettier"],
"env": {
"browser": true,
"jasmine": true,
"jest": true
},
"rules": {
"prettier/prettier": ["error", { "singleQuote": true }]
},
"settings": {
"react": {
"pragma": "React",
"version": "detect"
}
},
"parser": "@typescript-eslint/parser"
}
and in your .eslintignore add any paths you don't want linted. In my case, I want to exclude my tests folders and the service worker that is packaged with CRA
src/registerServiceWorker.js
src/**/__tests__/**
In your package.json
file we're going to add a new scripts file that will allow us to run our linter. Next to your react start
, build
, and test
scripts add
"lint:fix": "eslint './src/**/*.{ts,tsx}'",
our next step assuming we've built a brand new Create React App project is to create our first TypeScript file. Go ahead and rename App.js
to App.tsx
and run npm start
in your terminal. CRA will detect this is a TypeScript project and automatically add a tsconfig.json file for you. Running npm run lint
will now get you output of your linted code within your terminal window. If you're using VSCode install the ESLint extension to get in editor highlighting. Now open up your App.tsx
file and it should look like this
Hovering your mouse over the render
method should reveal two ESLint errors specific to TypeScript.
Missing accessibility modifier on method definition render.eslint(@typescript-eslint/explicit-member-accessibility)
Missing return type on function.eslint(@typescript-eslint/explicit-function-return-type)
In editor highlighting will let you know if your code is violating the configured linter rules without having to explicitly run the lint
script. If we want to disable these rules we can add
"@typescript-eslint/explicit-member-accessibility": 0,
"@typescript-eslint/explicit-function-return-type": 0,
to our rules configuration in eslintrc.json
. This is where we can disable rules, enable new rules and customize the default configuration that we've extended. In some cases certain linting issues can be auto-corrected by appending --fix
to npm run lint
.
If using VSCode in your settings.json
add the following to enable auto-fix on save,
"eslint.validate": [
"javascript",
"javascriptreact",
{
"language": "typescript",
"autoFix": true
},
{
"language": "typescriptreact",
"autoFix": true
}
],
Top comments (20)
Hey, how did you deal with the instance of ESLint that's built into CRA?
I've tried what you've done here previously, but CRA was detecting a "conflicting" version of ESLint and crashing. In fact, not so long ago, the CRA team mentioned it explicitly, that there's no way to set up a custom ESLint config yet. Has that been fixed or have you found a different approach?
I always had problems when a Eslint + Prettier tutorial tells you to add the eslint package along with the prettier stuff in a Create React App (CRA) project. Doing this lately tends to install Eslint 7 and all kinds of errors crop up due to a version conflict with the eslint used internally by the CRA scripts (version 6.6.0 I believe). This is why Ben's tutorial works, it simply gets the Prettier and Prettier packages up and running to work with the version of eslint that CRA and the CRA scripts use out of the box.
I suspect if one really wants the latest Eslint installed, you'd have to run the eject script and then dive in to the CRA config files to change out the eslint versions.
I read things more carefully and realized I misunderstood what exactly CRA was complaining about. It didn't like the fact that I installed a different version of ESLint, but once I swapped it for CRA's version, it was fine.
However, I noticed that you don't install ESLint in this article at all? How are you calling it in your scripts then? Is it installed globally?
You get ESLint for free when you install CRA so there's no need to install it in your package.json. I have experienced the same warning you're describing here when attempting to install my own version of ESLint. I uninstalled ESLint in my package.json and everything seems to be running as expected. I'm not sure regarding the restriction of ESLint configs, I have always been able to successfully set up lint configs though in the past opted for TSLint
It's worth nothing that this configuration was tested with the following versions of react/react-dom and react scripts
It could work to just keep using ESLint installed through CRA, but the VSCode ESLint extension doesn't seem to pick it up, of it's not listed among your dependencies. Plus, I don't think it's a good practice to reference a dependency in your code that you don't install manually... But can work for sure.
I agree, there should be some concern over this if a dependency higher up in the tree you don't have control over happens to change than dependent libraries downline could potentially cause issues. This is also the case when using any libraries that depend on Jest as well which also comes prepackaged with CRA. Given that these libraries are the new standard for TS linting with ESLint with full community support my hope is that there will be reasonable support for the latest versions of ESLint. I will mention up above as well this will be solved with CRA 3.0 that will include these libraries OOTB.
Thanks to your guide I was able to fix the CRA's own eslint that was failing on
as
withParsing error: Unexpected token, expected ","
by adding theses lines topackage.json
.Why are you using your own eslint related files instead of the
eslintConfig
that is already present inpackage.json
? Did you remove the config frompackage.json
or do you keep it there, having two eslint configurations? Is your solution still using CRA's internal mechanisms or is it something completely custom?I'm not using an
eslintConfig
in my package.json. Using the.eslintrc.json
is the only place I have added any configurations. This is just my preference,eslintConfig
inpackage.json
is also a valid approach. It just depends on how you like to structure your projectBefore running "npm start" ensure you "npm installl typescript --save-dev".
Eslint doesn't work for me. The lint command fails with.
Both my .eslintignore and .eslintrc.json are identical copy and paste. I used "npx create-react-app eslint-integration-typescript-example"
I can see that the file does have linting suggestions in the UI. But "npm run lint" doesn't work
Would really appreciate some guidance. This is the third guide I've tried to follow, each time with a fresh "CRA"
It works fine with standard javascript and I managed to get that to work as shown in this repo github.com/gruckion/eslint-integra... EDIT < doesn't work here either
The currently broken repo is here, github.com/gruckion/eslint-integra....
If you are having the same issue I was the cause is;
In order to get this to work, I had to remove the single quotes.
I am not sure why the single quote approach doesn't work for me. I read over the documentation and found it is called "glob" notation and it depends on the console your using (I am using git bash).
Placing your glob in double quotes will use nodes glob format. If you want to test it and don't want to globally install eslint use;
npx eslint './src/**/*.{ts,tsx}'
This works fine for me. with and without double or single quotes.
eslint.org/docs/user-guide/command...
If anyone has any idea why I can't run the script from my package.json with single quotes I would love to know.
It's an oddity of the operating system, I bet you were working with a windows 10 machine.
I got the exact same error, this is what I did.
lint: "eslint \"./src/*/.{ts,tsx}\""
stackoverflow.com/questions/481043...
thank you. It works in Win10 Pro now.
I can't get the prettier to run for some rules. One of them is "jsx-max-props-per-line".
This is how I specified -
Tried almost every permutation and combination. Please note that I only have eslint plugin on vscode enabled. No other linters are present in editor. Can someone please help!
This is due to 'printWidth' property in the .prettierrc configuration file. By default, it's 120. For me, 80 works great and shows props in a new line.
module.exports = {
semi: true,
trailingComma: "all",
singleQuote: true,
printWidth: 80,
tabWidth: 4
}
prettier.io/docs/en/options.html#p...
I have the same problem. Have you found a solution?
Hey Ben,
Thanks for putting this post together.
Something didn't really work for me or I expected something it was not supposed to offer.
I have a similar configuration to what you are suggesting and if I run npx eslint src/App.tsx, I get:
6:9 error 'chaire' is assigned a value but never used @typescript-eslint/no-unused-vars
Notice that it is an "error". When I run npm start, react-script kicks in and as the app is starting I get (in my command line window):
Compiled with warnings.
./src/App.tsx
Line 6: 'chaire' is assigned a value but never used @typescript-eslint/no-unused-vars
Note that it is a warning and therefore isn't respecting my eslint configuration. And I really want it to be an error!!! :)
Here's my lint config:
module.exports = {
"extends": [
"react-app",
"eslint:recommended",
"plugin:react/recommended",
"plugin:@typescript-eslint/recommended",
"prettier/@typescript-eslint",
"plugin:prettier/recommended"
],
"plugins": [
"react",
"@typescript-eslint",
"prettier"
],
"env": {
"browser": true,
"jasmine": true,
"jest": true
},
"rules": {
"prettier/prettier": [
"error", {
"singleQuote": true,
"tabWidth": 4
}
],
"@typescript-eslint/no-unused-vars": ["error", {
"vars": "all",
"args": "after-used",
"ignoreRestSiblings": false
}]
},
"settings": {
"react": {
"pragma": "React",
"version": "detect"
}
},
"parser": "@typescript-eslint/parser"
}
Regards,
Bruno
I copied the project to another folder, node_modules and all (no changes). Turns out now I get an error when react-scripts start runs:
TypeScript error in C:/BitB/auth-ui/src/App.tsx(6,11):
'chaire' is declared but its value is never read. TS6133
Looks like a typescript error and not a lint error, but I'll take it :)
However, I tried with a less problematic rule "semi": "error" and in my code import './App.css' without semicolon.
npx eslint src/App.tsx shows:
25:2 error Missing semicolon semi
But react-scripts start doesn't care about it.
Any help would be appreciated.
Hi!
I believe there is an error with
lint:fix
command.It is not the fix :) It should look like this: