From f5f98a703361fa88af13e3e4728ce76d65dbc104 Mon Sep 17 00:00:00 2001 From: Ian Schmitz Date: Sun, 24 Feb 2019 15:54:35 -0800 Subject: [PATCH 1/4] Initial pass adding typescript-eslint --- packages/eslint-config-react-app/index.js | 64 +++++++++++++++++++ packages/eslint-config-react-app/package.json | 2 + .../react-scripts/config/webpack.config.js | 2 +- packages/react-scripts/package.json | 2 + 4 files changed, 69 insertions(+), 1 deletion(-) diff --git a/packages/eslint-config-react-app/index.js b/packages/eslint-config-react-app/index.js index f83ed06a10..9698394311 100644 --- a/packages/eslint-config-react-app/index.js +++ b/packages/eslint-config-react-app/index.js @@ -52,6 +52,70 @@ module.exports = { }, }, + overrides: { + files: ['**/*.ts', '**/*.tsx'], + parser: '@typescript-eslint/parser', + parserOptions: { + ecmaVersion: 2018, + sourceType: 'module', + ecmaFeatures: { + jsx: true, + }, + + // typescript-eslint specific options + // TODO: Get these paths from somewhere so the parser has type info + // project: './tsconfig.json', + // tsconfigRootDir: '../../', + // TODO: Do we want to warn if version is unsupported? This could be a source of pain as new versions of TS come out and users upgrade + warnOnUnsupportedTypeScriptVersion: true, + }, + plugins: ['@typescript-eslint'], + rules: { + // These ESLint rules are known to cause issues with typescript-eslint + // See https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/src/configs/recommended.json + camelcase: 'off', + indent: 'off', + 'no-array-constructor': 'off', + 'no-unused-vars': 'off', + + // TODO: Strip out unused rules + + // '@typescript-eslint/adjacent-overload-signatures': 'warn', + // '@typescript-eslint/array-type': 'warn', + // '@typescript-eslint/ban-types': 'warn', + // '@typescript-eslint/camelcase': 'error', + // '@typescript-eslint/class-name-casing': 'error', + // '@typescript-eslint/explicit-function-return-type': 'warn', + // '@typescript-eslint/explicit-member-accessibility': 'error', + // '@typescript-eslint/indent': 'error', + // '@typescript-eslint/interface-name-prefix': 'error', + // '@typescript-eslint/member-delimiter-style': 'error', + '@typescript-eslint/no-angle-bracket-type-assertion': 'warn', + '@typescript-eslint/no-array-constructor': 'warn', + // '@typescript-eslint/no-empty-interface': 'error', + // '@typescript-eslint/no-explicit-any': 'warn', + // '@typescript-eslint/no-inferrable-types': 'error', + // '@typescript-eslint/no-misused-new': 'error', + '@typescript-eslint/no-namespace': 'error', + // '@typescript-eslint/no-non-null-assertion': 'error', + // '@typescript-eslint/no-object-literal-type-assertion': 'error', + // '@typescript-eslint/no-parameter-properties': 'error', + // '@typescript-eslint/no-triple-slash-reference': 'error', + '@typescript-eslint/no-unused-vars': [ + 'warn', + { + args: 'none', + ignoreRestSiblings: true, + }, + ], + // '@typescript-eslint/no-use-before-define': 'warn', + // '@typescript-eslint/no-var-requires': 'error', + // '@typescript-eslint/prefer-interface': 'error', + // '@typescript-eslint/prefer-namespace-keyword': 'error', + // '@typescript-eslint/type-annotation-spacing': 'error', + }, + }, + rules: { // http://eslint.org/docs/rules/ 'array-callback-return': 'warn', diff --git a/packages/eslint-config-react-app/package.json b/packages/eslint-config-react-app/package.json index 24fb6d4f5f..5c38619663 100644 --- a/packages/eslint-config-react-app/package.json +++ b/packages/eslint-config-react-app/package.json @@ -11,6 +11,8 @@ "index.js" ], "peerDependencies": { + "@typescript-eslint/eslint-plugin": "1.x", + "@typescript-eslint/parser": "1.x", "babel-eslint": "9.x", "eslint": "5.x", "eslint-plugin-flowtype": "2.x", diff --git a/packages/react-scripts/config/webpack.config.js b/packages/react-scripts/config/webpack.config.js index f6c0e7a237..51d6ce9c72 100644 --- a/packages/react-scripts/config/webpack.config.js +++ b/packages/react-scripts/config/webpack.config.js @@ -304,7 +304,7 @@ module.exports = function(webpackEnv) { // First, run the linter. // It's important to do this before Babel processes the JS. { - test: /\.(js|mjs|jsx)$/, + test: /\.(js|mjs|jsx|ts|tsx)$/, enforce: 'pre', use: [ { diff --git a/packages/react-scripts/package.json b/packages/react-scripts/package.json index b17fd14ce3..c290580f1c 100644 --- a/packages/react-scripts/package.json +++ b/packages/react-scripts/package.json @@ -26,6 +26,8 @@ "dependencies": { "@babel/core": "7.2.2", "@svgr/webpack": "4.1.0", + "@typescript-eslint/eslint-plugin": "1.4.1", + "@typescript-eslint/parser": "1.4.1", "babel-core": "7.0.0-bridge.0", "babel-eslint": "9.0.0", "babel-jest": "23.6.0", From b3592c1e2a21d8a96353dd24b096e7626bbcac24 Mon Sep 17 00:00:00 2001 From: Ian Schmitz Date: Mon, 25 Feb 2019 16:09:00 -0800 Subject: [PATCH 2/4] Add warning to shared rule set --- packages/eslint-config-react-app/index.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/eslint-config-react-app/index.js b/packages/eslint-config-react-app/index.js index 9698394311..72e82e2b47 100644 --- a/packages/eslint-config-react-app/index.js +++ b/packages/eslint-config-react-app/index.js @@ -116,6 +116,8 @@ module.exports = { }, }, + // NOTE: When adding rules here, you need to make sure they are compatible with + // `typescript-eslint`, as some rules such as `no-array-constructor` aren't compatible. rules: { // http://eslint.org/docs/rules/ 'array-callback-return': 'warn', From 60ecfc8ca9baf228ac621a7e830ff0d879c2d69d Mon Sep 17 00:00:00 2001 From: Ian Schmitz Date: Thu, 14 Mar 2019 19:20:48 -0700 Subject: [PATCH 3/4] Add documentation for setting up VSCode extension --- docusaurus/docs/setting-up-your-editor.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/docusaurus/docs/setting-up-your-editor.md b/docusaurus/docs/setting-up-your-editor.md index d99dca818c..869592d291 100644 --- a/docusaurus/docs/setting-up-your-editor.md +++ b/docusaurus/docs/setting-up-your-editor.md @@ -28,6 +28,19 @@ You would need to install an ESLint plugin for your editor first. Then, add a fi } ``` +If you're using TypeScript and Visual Studio Code, the [ESLint Visual Studio Code extension](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint#overview) currently [doesn't have TypeScript support enabled by default](https://github.com/Microsoft/vscode-eslint/issues/609). To enable TypeScript support in the ESLint extension, add the following to your project's Visual Studio Code settings file, located at `.vscode/settings.json` (you can create this file if it doesn't already exist): + +```json +{ + "eslint.validate": [ + "javascript", + "javascriptreact", + { "language": "typescript", "autoFix": true }, + { "language": "typescriptreact", "autoFix": true } + ] +} +``` + Now your editor should report the linting warnings. Note that even if you edit your `.eslintrc.json` file further, these changes will **only affect the editor integration**. They won’t affect the terminal and in-browser lint output. This is because Create React App intentionally provides a minimal set of rules that find common mistakes. From 4d3053597d6a6dcb6c15e9866f83cd0fb9fea805 Mon Sep 17 00:00:00 2001 From: Ian Schmitz Date: Thu, 14 Mar 2019 20:01:18 -0700 Subject: [PATCH 4/4] Provide tsconfig path to typescript-eslitn --- packages/eslint-config-react-app/index.js | 45 +++++++---------------- 1 file changed, 14 insertions(+), 31 deletions(-) diff --git a/packages/eslint-config-react-app/index.js b/packages/eslint-config-react-app/index.js index 72e82e2b47..816dca1b4e 100644 --- a/packages/eslint-config-react-app/index.js +++ b/packages/eslint-config-react-app/index.js @@ -21,7 +21,17 @@ // This is dangerous as it hides accidentally undefined variables. // We blacklist the globals that we deem potentially confusing. // To use them, explicitly reference them, e.g. `window.name` or `window.status`. -var restrictedGlobals = require('confusing-browser-globals'); +const restrictedGlobals = require('confusing-browser-globals'); + +// The following is copied from `react-scripts/config/paths.js`. +const path = require('path'); +const fs = require('fs'); +// Make sure any symlinks in the project folder are resolved: +// https://github.com/facebook/create-react-app/issues/637 +const appDirectory = fs.realpathSync(process.cwd()); +const resolveApp = relativePath => path.resolve(appDirectory, relativePath); +const projectRootPath = resolveApp('.'); +const tsConfigPath = resolveApp('tsconfig.json'); module.exports = { root: true, @@ -63,10 +73,8 @@ module.exports = { }, // typescript-eslint specific options - // TODO: Get these paths from somewhere so the parser has type info - // project: './tsconfig.json', - // tsconfigRootDir: '../../', - // TODO: Do we want to warn if version is unsupported? This could be a source of pain as new versions of TS come out and users upgrade + project: tsConfigPath, + tsconfigRootDir: projectRootPath, warnOnUnsupportedTypeScriptVersion: true, }, plugins: ['@typescript-eslint'], @@ -78,29 +86,9 @@ module.exports = { 'no-array-constructor': 'off', 'no-unused-vars': 'off', - // TODO: Strip out unused rules - - // '@typescript-eslint/adjacent-overload-signatures': 'warn', - // '@typescript-eslint/array-type': 'warn', - // '@typescript-eslint/ban-types': 'warn', - // '@typescript-eslint/camelcase': 'error', - // '@typescript-eslint/class-name-casing': 'error', - // '@typescript-eslint/explicit-function-return-type': 'warn', - // '@typescript-eslint/explicit-member-accessibility': 'error', - // '@typescript-eslint/indent': 'error', - // '@typescript-eslint/interface-name-prefix': 'error', - // '@typescript-eslint/member-delimiter-style': 'error', '@typescript-eslint/no-angle-bracket-type-assertion': 'warn', '@typescript-eslint/no-array-constructor': 'warn', - // '@typescript-eslint/no-empty-interface': 'error', - // '@typescript-eslint/no-explicit-any': 'warn', - // '@typescript-eslint/no-inferrable-types': 'error', - // '@typescript-eslint/no-misused-new': 'error', '@typescript-eslint/no-namespace': 'error', - // '@typescript-eslint/no-non-null-assertion': 'error', - // '@typescript-eslint/no-object-literal-type-assertion': 'error', - // '@typescript-eslint/no-parameter-properties': 'error', - // '@typescript-eslint/no-triple-slash-reference': 'error', '@typescript-eslint/no-unused-vars': [ 'warn', { @@ -108,15 +96,10 @@ module.exports = { ignoreRestSiblings: true, }, ], - // '@typescript-eslint/no-use-before-define': 'warn', - // '@typescript-eslint/no-var-requires': 'error', - // '@typescript-eslint/prefer-interface': 'error', - // '@typescript-eslint/prefer-namespace-keyword': 'error', - // '@typescript-eslint/type-annotation-spacing': 'error', }, }, - // NOTE: When adding rules here, you need to make sure they are compatible with + // NOTE: When adding rules here, you need to make sure they are compatible with // `typescript-eslint`, as some rules such as `no-array-constructor` aren't compatible. rules: { // http://eslint.org/docs/rules/