【问题标题】:React types files not working in React TypeScript (.tsx) file - Throwing ESLint errors for React ComponentReact 类型文件在 React TypeScript (.tsx) 文件中不起作用 - 为 React 组件引发 ESLint 错误
【发布时间】:2019-12-13 19:32:35
【问题描述】:

我有一个使用 Webpack、ESlint、Prettier 和 TypeScript 的 React 构建配置。

当我运行构建时,我似乎遇到了 TypeScript linting 错误,这些错误应该被 @typings/react 或 @typings/react-dom 包消除。

查看文档,我不需要为 React 组件定义可访问性修饰符或返回类型:https://www.typescriptlang.org/docs/handbook/jsx.html

这似乎与此处的问题相同:Missing return type on function - in react (typescript) code

但安装类型包并没有解决我的问题。请注意,我还尝试删除 @typings/react 包,因为 @typings/react-dom 有此作为依赖项,这并不能解决问题。

Webpack 配置

const webpack = require('webpack');
const CaseSensitivePathsPlugin = require('case-sensitive-paths-webpack-plugin');
const path = require('path');

const createWebpackConfig = () => {
  const isProd =
    process.env &&
    process.env.NODE_ENV &&
    process.env.NODE_ENV === 'production';

  return {
    entry: ['@babel/polyfill', './index.tsx'],
    mode: isProd ? 'production' : 'development',
    module: {
      rules: [
        {
          enforce: 'pre',
          test: /(\.jsx|\.js|\.ts|\.tsx)$/,
          exclude: /node_modules/,
          loader: 'eslint-loader'
        },
        {
          test: /(\.jsx|\.js)$/,
          exclude: /node_modules/,
          use: {
            loader: 'babel-loader',
            options: {
              presets: [
                '@babel/preset-react',
                [
                  '@babel/preset-env',
                  {
                    targets: 'cover 99.5% in GB'
                  }
                ]
              ],
              plugins: [
                '@babel/plugin-proposal-class-properties',
                '@babel/plugin-proposal-object-rest-spread'
              ],
              cacheDirectory: true
            }
          }
        },
        {
          test: /(\.tsx|\.ts)$/,
          exclude: /node_modules/,
          use: {
            loader: 'babel-loader',
            options: {
              presets: [
                '@babel/preset-typescript',
                '@babel/preset-react',
                [
                  '@babel/preset-env',
                  {
                    targets: 'cover 99.5% in GB'
                  }
                ]
              ],
              plugins: [
                '@babel/plugin-proposal-class-properties',
                '@babel/plugin-proposal-object-rest-spread'
              ],
              cacheDirectory: true
            }
          }
        }
      ]
    },
    resolve: {
      modules: [path.resolve(__dirname, '/'), 'node_modules'],
      extensions: ['.ts', '.tsx', '.js', '.jsx'],
      enforceExtension: false
    },
    target: 'web',
    optimization: {
      splitChunks: {
        chunks: 'all',
        maxInitialRequests: Infinity,
        minSize: 0,
        cacheGroups: {
          vendor: {
            test: /[\\/]node_modules[\\/]/,
            name: 'vendor'
          },
          main: {
            name: 'main'
          }
        }
      }
    },
    output: {
      path: path.join(__dirname, 'bundles'),
      filename: '[name].app.js',
      chunkFilename: '[name].bundle.js',
      pathinfo: true
    },
    plugins: [
      new CaseSensitivePathsPlugin(),
      new webpack.DefinePlugin({
        'process.env': {
          NODE_ENV: JSON.stringify(isProd ? 'production' : 'development')
        }
      })
    ]
  };
};

module.exports = createWebpackConfig;

ESLint 配置

{
  "parser": "@typescript-eslint/parser", // Specifies the ESLint parser
  "extends": [
    "plugin:react/recommended",
    "plugin:@typescript-eslint/recommended", // Uses the recommended rules from the @typescript-eslint/eslint-plugin
    "prettier/@typescript-eslint", // Uses eslint-config-prettier to disable ESLint rules from @typescript-eslint/eslint-plugin that would conflict with prettier
    "plugin:prettier/recommended" // Enables eslint-plugin-prettier and displays prettier errors as ESLint errors. Make sure this is always the last configuration in the extends array.
  ],
  "parserOptions": {
    "ecmaVersion": 10, // Allows for the parsing of modern ECMAScript features
    "sourceType": "module", // Allows for the use of imports
    "jsx": true
  },
  "rules": {
    "prettier/prettier": [
      "error",
      {
        "singleQuote": true,
        "endOfLine": "auto"
      }
    ]
  }
}

tsconfig.json

{
  "compilerOptions": {
    "module": "esnext",
    "allowSyntheticDefaultImports": true,
    "allowJs": true,
    "jsx": "preserve"
  },
  "exclude": ["node_modules"]
}

package.json

{
  "name": "reacttypescripttest",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "dev": "cross-env NODE_ENV=development webpack --config ./webpack.config.js --progress --colors --watch --display-error-details"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "@babel/core": "^7.5.5",
    "@babel/plugin-proposal-class-properties": "^7.5.5",
    "@babel/plugin-proposal-object-rest-spread": "^7.5.5",
    "@babel/polyfill": "^7.4.4",
    "@babel/preset-env": "^7.5.5",
    "@babel/preset-react": "^7.0.0",
    "@babel/preset-typescript": "^7.3.3",
    "@types/react": "^16.8.24",
    "@types/react-dom": "^16.8.5",
    "@typescript-eslint/eslint-plugin": "^1.13.0",
    "@typescript-eslint/parser": "^1.13.0",
    "babel-loader": "^8.0.6",
    "case-sensitive-paths-webpack-plugin": "^2.2.0",
    "cross-env": "^5.2.0",
    "eslint": "^6.1.0",
    "eslint-config-prettier": "^6.0.0",
    "eslint-loader": "^2.2.1",
    "eslint-plugin-prettier": "^3.1.0",
    "eslint-plugin-react": "^7.14.3",
    "mini-css-extract-plugin": "^0.8.0",
    "prettier": "^1.18.2",
    "prettier-eslint": "^9.0.0",
    "react": "^16.8.6",
    "react-dom": "^16.8.6",
    "typescript": "^3.5.3",
    "webpack-cli": "^3.3.6"
  },
  "devDependencies": {
    "webpack": "^4.39.1"
  }
}

导致错误的文件 (index.tsx)

import React from 'react';
import ReactDOM from 'react-dom';

class App extends React.Component {
  render() {
    return <div>Running!</div>;
  }
}

ReactDOM.render(<App />, document.getElementById('app'));

错误

  5:3  error    Missing accessibility modifier on method definition render  @typescript-eslint/explicit-member-accessibility
  5:9  warning  Missing return type on function                             @typescript-eslint/explicit-function-return-type

【问题讨论】:

    标签: reactjs typescript eslint


    【解决方案1】:

    第一个错误Missing accessibility modifier on method definition render 是说您没有将render 方法声明为publicprivate 或任何其他类型(more reading on types。使用Typescript 时,所有类方法都需要声明因此,取决于您是否希望在您的类实例之外访问它们。对于render 方法,它应该是公共的。下面的代码应该很适合您:

    public render() {
       return <div>Running!</div>;
    }
    

    当您遇到第二个错误时,这意味着您的 linter 期望 render 方法已声明其执行的输出是什么。 render 方法的正确类型是 React.ReactNode,因此您的最终代码应如下所示(假设您没有在前面的 import 语句中导入 ReactNode

    public render(): React.ReactNode {
       return <div>Running!</div>;
    }
    

    编辑 1

    即使 TS 本身不需要所有这些注释,您使用的 linter 也需要。请参阅他们的default rules- 如您所见,您遇到问题的规则并未关闭。解决方案是在您的应用程序 eslint 配置中禁用它们,如下所示:

    "rules": {
       "@typescript-eslint/explicit-function-return-type": "off",
       "@typescript-eslint/explicit-member-accessibility": "off"
    }
    

    【讨论】:

    • 我理解错误的含义,(或者至少我理解第一个错误)但是 Typings 文件应该意味着我不需要注释 React 方法,如这里的文档示例中所示: typescriptlang.org/docs/handbook/jsx.html#class-component 因为他们应该通知编译器。将 TS 注释添加到每个组件上的默认 React Class 方法并不是很有用,并且会增加代码量。
    • 即使 TS 本身不需要所有这些注释,您使用的 linter 也需要。查看它们的默认值github.com/typescript-eslint/typescript-eslint/blob/master/…。如您所见,您遇到问题的规则并未关闭。解决方案是在您的应用程序 eslint 配置中禁用它们
    • 是否可以仅为 React 类禁用这些?我的应用程序中还有其他类,打开它们仍然很有用。
    • 无法定位 React 类,但您可以禁用每个目录的特定规则。这可能会导致结构更复杂,维护 Eslint 规则可能会更棘手,但应该可以解决您的问题。看到这个stackoverflow.com/questions/41316551/…,有两种解决方案如何做到这一点
    【解决方案2】:

    如果有人遇到这种情况并且已经使用 tsx 文件。确保您已将 vscode 配置为将 tsx 文件与 TypescriptReact 相关联,而不仅仅是 Typescript。打开 tsx 文件后,右下角单击 Typescript 并设置关联。

    【讨论】:

    • 您能否更新您的答案以说明如何执行此操作?
    猜你喜欢
    • 1970-01-01
    • 2021-03-24
    • 2016-10-09
    • 2021-10-04
    • 2021-07-13
    • 2017-09-23
    • 1970-01-01
    • 2019-08-17
    • 2019-10-23
    相关资源
    最近更新 更多