Add AirBnb TypeScript overrides for linting
AirBnb only imports JavaScript rules and some fail for TypeScript files. This commit overrides those rules with TypeScript equivalents. Changes here can be mostly replaced when Vue natively support TypeScript for Airbnb (vuejs/eslint-config-airbnb#23). Enables @typescript-eslint/indent even though it's broken and it will not be fixed typescript-eslint/typescript-eslint#1824 until prettifier is used, because it is still useful. Change broken rules with TypeScript variants: - `no-useless-constructor` eslint/eslint#14118 typescript-eslint/typescript-eslint#873 - `no-shadow` eslint/eslint#13044 typescript-eslint/typescript-eslint#2483 typescript-eslint/typescript-eslint#325 typescript-eslint/typescript-eslint#2552 typescript-eslint/typescript-eslint#2484 typescript-eslint/typescript-eslint#2466
This commit is contained in:
175
.eslintrc.js
175
.eslintrc.js
@@ -1,4 +1,9 @@
|
||||
const { rules: baseBestPracticesRules } = require('eslint-config-airbnb-base/rules/best-practices');
|
||||
const { rules: baseErrorsRules } = require('eslint-config-airbnb-base/rules/errors');
|
||||
const { rules: baseES6Rules } = require('eslint-config-airbnb-base/rules/es6');
|
||||
const { rules: baseImportsRules } = require('eslint-config-airbnb-base/rules/imports');
|
||||
const { rules: baseStyleRules } = require('eslint-config-airbnb-base/rules/style');
|
||||
const { rules: baseVariablesRules } = require('eslint-config-airbnb-base/rules/variables');
|
||||
|
||||
module.exports = {
|
||||
root: true,
|
||||
@@ -39,6 +44,18 @@ module.exports = {
|
||||
mocha: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ['**/*.ts?(x)', '**/*.d.ts'],
|
||||
parserOptions: {
|
||||
// Setting project is required for some rules such as @typescript-eslint/dot-notation,
|
||||
// @typescript-eslint/return-await and @typescript-eslint/no-throw-literal.
|
||||
// If this property is missing they fail due to missing parser.
|
||||
project: ['./tsconfig.json'],
|
||||
},
|
||||
rules: {
|
||||
...getTypeScriptOverrides(),
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ['**/tests/**/*.{j,t}s?(x)'],
|
||||
rules: {
|
||||
@@ -113,3 +130,161 @@ function getOpinionatedRuleOverrides() {
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
function getTypeScriptOverrides() {
|
||||
/*
|
||||
Here until Vue supports AirBnb Typescript overrides (vuejs/eslint-config-airbnb#23).
|
||||
Based on `eslint-config-airbnb-typescript`.
|
||||
Source: https://github.com/iamturns/eslint-config-airbnb-typescript/blob/v16.1.0/lib/shared.js
|
||||
It cannot be used directly due to compilation errors.
|
||||
*/
|
||||
return {
|
||||
'brace-style': 'off',
|
||||
'@typescript-eslint/brace-style': baseStyleRules['brace-style'],
|
||||
|
||||
camelcase: 'off',
|
||||
'@typescript-eslint/naming-convention': [
|
||||
'error',
|
||||
{ selector: 'variable', format: ['camelCase', 'PascalCase', 'UPPER_CASE'] },
|
||||
{ selector: 'function', format: ['camelCase', 'PascalCase'] },
|
||||
{ selector: 'typeLike', format: ['PascalCase'] },
|
||||
],
|
||||
|
||||
'comma-dangle': 'off',
|
||||
'@typescript-eslint/comma-dangle': [
|
||||
baseStyleRules['comma-dangle'][0],
|
||||
{
|
||||
...baseStyleRules['comma-dangle'][1],
|
||||
enums: baseStyleRules['comma-dangle'][1].arrays,
|
||||
generics: baseStyleRules['comma-dangle'][1].arrays,
|
||||
tuples: baseStyleRules['comma-dangle'][1].arrays,
|
||||
},
|
||||
],
|
||||
|
||||
'comma-spacing': 'off',
|
||||
'@typescript-eslint/comma-spacing': baseStyleRules['comma-spacing'],
|
||||
|
||||
'default-param-last': 'off',
|
||||
'@typescript-eslint/default-param-last': baseBestPracticesRules['default-param-last'],
|
||||
|
||||
'dot-notation': 'off',
|
||||
'@typescript-eslint/dot-notation': baseBestPracticesRules['dot-notation'],
|
||||
|
||||
'func-call-spacing': 'off',
|
||||
'@typescript-eslint/func-call-spacing': baseStyleRules['func-call-spacing'],
|
||||
|
||||
// ❌ Broken for some cases, but still useful.
|
||||
// Here until Prettifier is used.
|
||||
indent: 'off',
|
||||
'@typescript-eslint/indent': baseStyleRules.indent,
|
||||
|
||||
'keyword-spacing': 'off',
|
||||
'@typescript-eslint/keyword-spacing': baseStyleRules['keyword-spacing'],
|
||||
|
||||
'lines-between-class-members': 'off',
|
||||
'@typescript-eslint/lines-between-class-members': baseStyleRules['lines-between-class-members'],
|
||||
|
||||
'no-array-constructor': 'off',
|
||||
'@typescript-eslint/no-array-constructor': baseStyleRules['no-array-constructor'],
|
||||
|
||||
'no-dupe-class-members': 'off',
|
||||
'@typescript-eslint/no-dupe-class-members': baseES6Rules['no-dupe-class-members'],
|
||||
|
||||
'no-empty-function': 'off',
|
||||
'@typescript-eslint/no-empty-function': baseBestPracticesRules['no-empty-function'],
|
||||
|
||||
'no-extra-parens': 'off',
|
||||
'@typescript-eslint/no-extra-parens': baseErrorsRules['no-extra-parens'],
|
||||
|
||||
'no-extra-semi': 'off',
|
||||
'@typescript-eslint/no-extra-semi': baseErrorsRules['no-extra-semi'],
|
||||
|
||||
// ❌ Fails due to missing parser
|
||||
// 'no-implied-eval': 'off',
|
||||
// 'no-new-func': 'off',
|
||||
// '@typescript-eslint/no-implied-eval': baseBestPracticesRules['no-implied-eval'],
|
||||
|
||||
'no-loss-of-precision': 'off',
|
||||
'@typescript-eslint/no-loss-of-precision': baseErrorsRules['no-loss-of-precision'],
|
||||
|
||||
'no-loop-func': 'off',
|
||||
'@typescript-eslint/no-loop-func': baseBestPracticesRules['no-loop-func'],
|
||||
|
||||
'no-magic-numbers': 'off',
|
||||
'@typescript-eslint/no-magic-numbers': baseBestPracticesRules['no-magic-numbers'],
|
||||
|
||||
'no-redeclare': 'off',
|
||||
'@typescript-eslint/no-redeclare': baseBestPracticesRules['no-redeclare'],
|
||||
|
||||
// ESLint variant does not work with TypeScript enums.
|
||||
'no-shadow': 'off',
|
||||
'@typescript-eslint/no-shadow': baseVariablesRules['no-shadow'],
|
||||
|
||||
'no-throw-literal': 'off',
|
||||
'@typescript-eslint/no-throw-literal': baseBestPracticesRules['no-throw-literal'],
|
||||
|
||||
'no-unused-expressions': 'off',
|
||||
'@typescript-eslint/no-unused-expressions': baseBestPracticesRules['no-unused-expressions'],
|
||||
|
||||
'no-unused-vars': 'off',
|
||||
'@typescript-eslint/no-unused-vars': baseVariablesRules['no-unused-vars'],
|
||||
|
||||
// https://erkinekici.com/articles/linting-trap#no-use-before-define
|
||||
// 'no-use-before-define': 'off',
|
||||
// '@typescript-eslint/no-use-before-define': baseVariablesRules['no-use-before-define'],
|
||||
|
||||
// ESLint variant does not understand TypeScript constructors.
|
||||
// eslint/eslint/#14118, typescript-eslint/typescript-eslint#873
|
||||
'no-useless-constructor': 'off',
|
||||
'@typescript-eslint/no-useless-constructor': baseES6Rules['no-useless-constructor'],
|
||||
|
||||
quotes: 'off',
|
||||
'@typescript-eslint/quotes': baseStyleRules.quotes,
|
||||
|
||||
semi: 'off',
|
||||
'@typescript-eslint/semi': baseStyleRules.semi,
|
||||
|
||||
'space-before-function-paren': 'off',
|
||||
'@typescript-eslint/space-before-function-paren': baseStyleRules['space-before-function-paren'],
|
||||
|
||||
'require-await': 'off',
|
||||
'@typescript-eslint/require-await': baseBestPracticesRules['require-await'],
|
||||
|
||||
'no-return-await': 'off',
|
||||
'@typescript-eslint/return-await': baseBestPracticesRules['no-return-await'],
|
||||
|
||||
'space-infix-ops': 'off',
|
||||
'@typescript-eslint/space-infix-ops': baseStyleRules['space-infix-ops'],
|
||||
|
||||
'object-curly-spacing': 'off',
|
||||
'@typescript-eslint/object-curly-spacing': baseStyleRules['object-curly-spacing'],
|
||||
|
||||
'import/extensions': [
|
||||
baseImportsRules['import/extensions'][0],
|
||||
baseImportsRules['import/extensions'][1],
|
||||
{
|
||||
...baseImportsRules['import/extensions'][2],
|
||||
ts: 'never',
|
||||
tsx: 'never',
|
||||
},
|
||||
],
|
||||
|
||||
// Changes required is not yet implemented:
|
||||
// 'import/no-extraneous-dependencies': [
|
||||
// baseImportsRules['import/no-extraneous-dependencies'][0],
|
||||
// {
|
||||
// ...baseImportsRules['import/no-extraneous-dependencies'][1],
|
||||
// devDependencies: baseImportsRules[
|
||||
// 'import/no-extraneous-dependencies'
|
||||
// ][1].devDependencies.reduce((result, devDep) => {
|
||||
// const toAppend = [devDep];
|
||||
// const devDepWithTs = devDep.replace(/\bjs(x?)\b/g, 'ts$1');
|
||||
// if (devDepWithTs !== devDep) {
|
||||
// toAppend.push(devDepWithTs);
|
||||
// }
|
||||
// return [...result, ...toAppend];
|
||||
// }, []),
|
||||
// },
|
||||
// ],
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user