什么是代码检查
代码检查主要是用来发现代码错误、统一代码风格。
在 JavaScript 项目中,我们一般使用ESLint来进行代码检查。它通过插件化的特性极大的丰富了适用范围,搭配typescript-eslint-parser之后,甚至可以用来检查 TypeScript 代码。
TSLint 与 ESLint 类似,不过除了能检查常规的 js 代码风格之外,TSLint 还能够通过 TypeScript 的语法解析,利用类型系统做一些 ESLint 做不到的检查。
由于性能问题,TypeScript 官方决定全面采用 ESLint,甚至把仓库(Repository)作为测试平台,而 ESLint 的 TypeScript 解析器也成为独立项目,专注解决双方兼容性问题。
JavaScript 代码检验工具 ESLint 在 TypeScript 团队发布全面采用 ESLint 之后,发布 typescript-eslint 项目,以集中解决 TypeScript 和 ESLint 兼容性问题。而 ESLint 团队将不再维护 typescript-eslint-parser,也不会在 Npm 上发布,TypeScript 解析器转移至Github 的 typescript-eslint/parser。
所以本篇文章主要围绕 typescript-eslint/parser 进行ts 与js 的并存检查
安装依赖
安装eslint
- 安装eslint 到本地
cnpm i eslint -D - 初始化配置文件(推荐尝试下这个命令,而不是直接拿别人写好的.eslintrc.xx文件)
./node_modules/.bin/eslint --init ./node_modules/.bin/eslint -h查看运行指令,运行想要检查的指令$ ./node_modules/.bin/eslint yourfile.js
安装 @typescript-eslint/parser 解析器
eslint 可以解析typescript 语法
cnpm i @typescript-eslint/parser -D
安装推荐插件
-
辅助解析.ts 文件
npm i @typescript-eslint/eslint-plugin -D -
安装格式化插件
使lint 工具专注于质量检查,同时避免lint 定义的格式语法与集成的格式化插件冲突
npm i prettier eslint-config-prettier -Deslint-config-prettier是一个禁用与Prettier冲突的规则的配置,确保将它放在extends数组的最后,这样它就有机会覆盖其他配置
-
使用Airbnb
Airbnb有两个配置,一个是基础的eslint-config-airbnb-base,另一个包含React规则的eslint-config-airbnb。
npm info "eslint-config-airbnb@latest" peerDependencies查看 peerDependencies,并安装相应的包
使用方法
在eslint.js 配置文件中 ,针对上述插件的添加配置文件
module.exports = {
// 预定义全局变量
env: {
browser: true,
commonjs: true,
node: true,
es6: true
},
parser: '@typescript-eslint/parser',
plugins: ['react', '@typescript-eslint'],
parserOptions: {
project: './tsconfig.json',
ecmaFeatures: {
jsx: true
}
},
settings: {
'import/resolver': {
webpack: {
config: './webpack/webpack.dev.config.js'
}
}
},
globals: {
window: true
},
root: true, //项目根目录,停止向上搜索配置文件
extends: [
'eslint:recommended',
'airbnb',
'plugin:@typescript-eslint/recommended',
'plugin:@typescript-eslint/eslint-recommended',
'prettier', // 禁用与Prettier 冲突的规则
'prettier/@typescript-eslint', // 针对添加的插件 弃用对应的格式化规则
'prettier/react' //eslint-config-airbnb 启用 eslint-plugin-react 规则,故在prettier 修改
],
rules: {
'array-bracket-spacing': ['error'],
'arrow-body-style': ['error', 'as-needed'],
'arrow-spacing': ['error'],
'block-spacing': ['error'],
'brace-style': ['error'],
camelcase: ['warn'],
'capitalized-comments': ['off'],
'comma-dangle': [
'error',
{
arrays: 'never',
objects: 'never',
imports: 'never',
exports: 'never',
functions: 'never'
}
],
'comma-spacing': ['error'],
'comma-style': ['error'],
'computed-property-spacing': ['error'],
curly: ['off'],
'dot-location': ['error', 'property'],
'dot-notation': ['off'],
'eol-last': ['off'],
'func-call-spacing': ['error'],
'func-name-matching': ['error'],
'generator-star-spacing': ['error'],
indent: [
'error',
4,
{
SwitchCase: 1
}
],
'jsx-quotes': ['error', 'prefer-single'],
'key-spacing': ['error'],
'keyword-spacing': ['error'],
'linebreak-style': ['error'],
'lines-around-comment': [
'off',
{
beforeLineComment: true
}
],
'lines-around-directive': ['error'],
'new-cap': ['off'],
'newline-after-var': ['off'],
'newline-before-return': ['off'],
'new-parens': ['error'],
'no-cond-assign': ['off'],
'no-console': ['off'],
'no-delete-var': ['off'],
'no-extra-bind': ['error'],
'no-extra-parens': [
'error',
'all',
{
returnAssign: false,
ignoreJSX: 'all',
enforceForArrowConditionals: false,
nestedBinaryExpressions: false
}
],
'no-floating-decimal': ['error'],
'no-lonely-if': ['error'],
'no-multiple-empty-lines': [
'error',
{
max: 1,
maxBOF: 0,
maxEOF: 0
}
],
'no-multi-spaces': ['error'],
'no-redeclare': ['error'],
'no-undef-init': ['error'],
'no-useless-computed-key': ['error'],
'no-useless-rename': ['error'],
'no-useless-return': ['error'],
'no-var': ['warn'],
'no-whitespace-before-property': ['error'],
'object-curly-newline': ['off'],
'object-curly-spacing': ['off'],
'object-shorthand': ['off'],
'operator-assignment': ['warn'],
'one-var': ['off'],
'one-var-declaration-per-line': ['error', 'initializations'],
'padded-blocks': ['off', 'never'],
'prefer-arrow-callback': ['off'],
'prefer-spread': ['off'],
'prefer-template': ['off'],
quotes: ['error', 'single'],
'quote-props': ['off', 'as-needed'],
'react/prop-types': ['off'],
'react/jsx-curly-spacing': ['error'],
'react/jsx-space-before-closing': ['off', 'never'],
'rest-spread-spacing': ['error'],
semi: ['off', 'never'],
'space-before-blocks': ['error'],
'space-before-function-paren': ['off', 'never'],
'space-in-parens': ['error', 'never'],
'space-infix-ops': ['error'],
'space-unary-ops': [
'error',
{
words: true,
nonwords: false
}
],
'template-curly-spacing': ['error'],
'yield-star-spacing': ['error'],
yoda: ['error'],
eqeqeq: ['off'],
'no-eval': ['off'],
'no-template-curly-in-string': ['off'],
'no-shadow': ['off'],
'no-return-assign': ['off'],
'global-require': ['off'],
'no-underscore-dangle': ['off'],
'func-names': ['off'],
'prefer-destructuring': ['off'],
'prefer-const': ['error'], // let与const 优先级
indent: ['off'],
'no-restricted-syntax': ['off'],
'guard-for-in': ['off'],
'no-continue': ['off'],
'no-extend-native': ['off'],
'no-param-reassign': ['off'],
'consistent-return': ['off'],
radix: ['off'],
'no-plusplus': ['off'],
'no-unused-expressions': ['off'],
'no-script-url': ['off'],
'no-restricted-globals': ['off'],
'import/no-cycle': ['off'],
'jsx-a11y/alt-text': ['off'],
'react/sort-comp': ['off'],
'react/destructuring-assignment': ['off'],
'import/no-webpack-loader-syntax': ['off'],
'react/jsx-indent': ['off'],
'react/jsx-indent-props': ['off'],
'react/jsx-filename-extension': ['error', { extensions: ['.ts', '.tsx', '.js', '.jsx'] }],
'react/jsx-one-expression-per-line': ['off'],
'@typescript-eslint/explicit-member-accessibility': ['off'],
'@typescript-eslint/interface-name-prefix': ['error', 'always'],
'react/no-access-state-in-setstate': ['off'],
'react/no-array-index-key': ['off'],
'jsx-a11y/click-events-have-key-events': ['off'],
'jsx-a11y/no-static-element-interactions': ['off'],
'jsx-a11y/anchor-is-valid': ['off'],
'react/jsx-wrap-multilines': ['off'],
'@typescript-eslint/explicit-function-return-type': [
'off',
{
allowExpressions: true,
allowTypedFunctionExpressions: true
}
],
'jsx-a11y/label-has-for': ['off'],
'jsx-a11y/label-has-associated-control': ['off'],
'react/jsx-boolean-value': ['off'],
// 'lines-between-class-member':['error'], // 默认打开,类成员有空格
'@typescript-eslint/no-var-requires': ['off'],
'@typescript-eslint/no-explicit-any': ['off'],
'@typescript-eslint/no-use-before-define': ['error', { functions: false }],
'import/no-extraneous-dependencies': ['error', { devDependencies: true }],
'import/order': ['off'],
'import/newline-after-import': ['off'],
'import/no-unresolved': [2, { commonjs: true, amd: true }]
}
};
运行eslint命令
在package.json 添加可执行命令
eslint -c ./.eslintrc.js --ext .js,.jsx,.ts,.tsx ./
eslint 默认检查js 文件,需要添加.ts 文件说明,--fix 默认修复选项,有时会导致自动修复错误,故不添加
vscode 中集成 eslint 检查typescript
默认情况下,ESLint扩展仅在javascript和javascriptreact文件上运行。要告诉它在TS文件上运行,您需要将eslint.validate设置更新为:
"eslint.validate": [
"javascript",
"javascriptreact",
"typescript",
"typescriptreact"
]