diff --git a/linters/.eslintrc.typescript.js b/linters/.eslintrc.typescript.js new file mode 100644 index 0000000000..dc5ccb64e6 --- /dev/null +++ b/linters/.eslintrc.typescript.js @@ -0,0 +1,97 @@ +module.exports = { + extends: [ + 'plugin:@typescript-eslint/eslint-recommended', + ], + parser: '@typescript-eslint/parser', + plugins: [ + '@typescript-eslint', + ], + settings: { + // Load /tsconfig.json to eslint + // https://github.com/import-js/eslint-plugin-import/issues/1485#issuecomment-571597574 + 'import/resolver': { + typescript: {}, + }, + }, + rules: { + + // Add .ts and .tsx to Airbnb's import/extensions config + 'import/extensions': [ + 'error', + 'ignorePackages', + { + js: 'never', + mjs: 'never', + jsx: 'never', + ts: 'never', + tsx: 'never', + }, + ], + + // Rules that exist in vanilla eslint but have typescript-specific replacements + 'no-shadow': 0, + '@typescript-eslint/no-shadow': 2, + + 'no-unused-vars': 0, + '@typescript-eslint/no-unused-vars': 2, + + 'no-use-before-define': 0, + '@typescript-eslint/no-use-before-define': 2, + + semi: 0, + '@typescript-eslint/semi': [2, 'always'], + + // Rules to guard against potentially dangerous or confusing practices + '@typescript-eslint/no-explicit-any': 2, + '@typescript-eslint/ban-types': 2, + + // Rules to enforce consistent formatting + '@typescript-eslint/type-annotation-spacing': 2, + '@typescript-eslint/member-delimiter-style': [2, { + multiline: { + delimiter: 'comma', + requireLast: true, + }, + singleline: { + delimiter: 'comma', + requireLast: false, + }, + }], + '@typescript-eslint/consistent-type-assertions': 2, + '@typescript-eslint/naming-convention': [ + 2, + { + selector: 'interface', + format: ['PascalCase'], + custom: { + // Prefixing interfaces with `I` is widely considered a form of Hungarian notation + // and is generally avoided. https://stackoverflow.com/a/41967120 + regex: '^I[A-Z]', + match: false, + }, + }, + ], + + // These rules can be turned off because typescript already checks for them + // https://github.com/typescript-eslint/typescript-eslint/blob/master/docs/getting-started/linting/FAQ.md#eslint-plugin-import + 'import/named': 0, + 'import/namespace': 0, + 'import/default': 0, + 'import/no-named-as-default-member': 0, + + // These rules can be computationally expensive. If linting is becoming slow, consider + // moving them to a separate script or tweaking their settings. + // https://github.com/typescript-eslint/typescript-eslint/blob/master/docs/getting-started/linting/FAQ.md#eslint-plugin-import + 'import/no-named-as-default': 2, + 'import/no-cycle': [ + 2, + { + maxDepth: 'āˆž', + + // If you don't need cycle detection to expand to external modules, + // override this to true to speed up linting. + ignoreExternal: false, + }, + ], + }, +}; diff --git a/linters/tslint.json b/linters/tslint.json deleted file mode 100644 index ef1e3c94bc..0000000000 --- a/linters/tslint.json +++ /dev/null @@ -1,161 +0,0 @@ -{ - "extends": ["tslint-eslint-rules"], - "rules": { - - // RECOMMENDATIONS - - "interface-name": [true, "never-prefix"], // Require interface names to not have an ā€œIā€ prefix - "deprecation": true, // Warn when deprecated APIs are used - "member-ordering": [ // Enforce member ordering - true, - { - "order": "fields-first" - } - ], - - // MODULES - - "no-duplicate-imports": true, // Disallow duplicate imports - - // ARROW FUNCTIONS - - "prefer-arrow-callback": 2, // Require arrow functions as callbacks - "arrow-spacing": [2, { // Require space before/after arrows - "before": true, - "after": true - }], - - // VARIABLES - - "variable-name": [ // Check variable names for various errors - true, - "ban-keywords", - "check-format", - "allow-leading-underscore", - "allow-pascal-case" - ], - "one-variable-per-declaration": true, // Disallow multiple variable definitions in the same declaration statement - "no-duplicate-variable": [ // Disallow duplicate variable declarations in the same block scope, including parameters - true, - "check-parameters" - ], - "no-unused-expression": true, // Disallow unused expression statements - "no-shadowed-variable": true, // Disallow shadowing variable declarations - "no-unused-variable": true, // Disallow unused imports, variables, functions and private class members - "no-use-before-declare": true, // Disallow usage of variables before their declaration - "no-var-keyword": true, // Disallow usage of the var keyword - "prefer-const": true, // Require const when not reassigned - - // OBJECTS - - "object-literal-shorthand": true, // Enforce use of ES6 object literal shorthand - - // TYPES - - "typedef": [ // Require type definitions to exist - true, - "parameter", - "property-declaration" - ], - "typedef-whitespace": [ // Enforce one space after type information - true, - { - "call-signature": "nospace", - "index-signature": "nospace", - "parameter": "nospace", - "property-declaration": "nospace", - "variable-declaration": "nospace" - } - ], - "no-any": true, // Disallow usage of any as a type declaration - "ban-types": [ // Disallow use of Object and String types - true, - ["Object"], - ["Boolean"], - ["String"], - ["Function"] - ], - "no-extra-boolean-cast": true, // Prevent unnecessary boolean cast - "no-invalid-regexp": true, // Disallow invalid regular expression strings in the RegExp constructor - "no-construct": true, // Disallow String/Number/Boolean constructors - "radix": true, // Require the radix parameter to be specified when calling parseInt - "no-bitwise": true, // Disallow bitwise operators - - // STRINGS - - "no-eval": true, // Disallow eval function invocations - "quotemark": [true, "single", "jsx-double"], // Prefer single quotes for strings - - // BLOCKS - - "forin": true, // Require a for ... in statement to be filtered with an if statement - "curly": [true, "ignore-same-line"], // Enforce braces for if/for/do/while statements - - // COMPARISON - - "no-duplicate-switch-case": true, // Prevent duplicate cases in switch statements - "no-conditional-assignment": true, // Disallow assignment within conditionals - "cyclomatic-complexity": [true, 8], // Enforce a threshold of cyclomatic complexity - "no-switch-case-fall-through": true, // Disallow falling through case statements - "triple-equals": [true, "allow-null-check"], // Require === and !==, allow null check - - // WHITESPACE - - "no-multi-spaces": [true], // Disallow multiple spaces - "whitespace": [ // Enforce whitespace style conventions - true, - "check-branch", - "check-decl", - "check-module", - "check-operator", - "check-separator", - "check-rest-spread", - "check-type", - "check-typecast", - "check-type-operator", - "check-preblock" - ], - "object-curly-spacing": [2, "always"], // Require spaces inside object curly braces - "indent": [true, "spaces", 4], // Enforce 4 spaces - "no-irregular-whitespace": true, // Disallow irregular whitespace - "no-trailing-whitespace": true, // Disallow trailing whitespace at the end of a line - "array-bracket-spacing": [2, "never"], // Disallow spaces inside of brackets - "eofline": true, // Require file to end with a newline - "max-line-length": [ // Disallow lines over 100 characters - true, - { - "limit": 100, - "ignore-pattern": "^import " - } - ], - - // SEMICOLONS - - "semicolon": [true, "always"], // Require semicolons - "no-extra-semi": true, // Disallow extra semicolons - - // COMMENTS - - "jsdoc-format": true, // Enforce basic format rules for JSDoc comments - "valid-jsdoc": [2, { // Require docblocks match params/return type - "requireParamDescription": false, - "requireReturnDescription": false, - "requireReturn": false - }], - "comment-format": [ // Require a space before comment - true, - "check-space" - ], - - // COMMAS - - "trailing-comma": [ // Require trailing commas - true, - { - "multiline": "always", - "singleline": "never" - } - ] - - } -} \ No newline at end of file