Skip to content

Commit

Permalink
Add rules that require type information (#250)
Browse files Browse the repository at this point in the history
* Add rules that require type information

* Run lint:fix

* Disable no-confusing-void-expression

* Fix rule typo

* Allow camelCase, PascalCase and UPPER_CASE for object literal properties

* Allow camelCase, PascalCase and UPPER_CASE for object literal methods

* Disable unbound-method

* Allow leading underscore in front of variables

* Enable no-throw-literal

* Enable restrict-template-expression

* Run lint:fix

* Fix tests

* Remove allowAny from restrict-template-expressions

* Re-enable unbound-method

* Fix rebase issue
  • Loading branch information
Mrtenz committed Nov 15, 2022
1 parent e2f8302 commit 32abef3
Show file tree
Hide file tree
Showing 5 changed files with 163 additions and 3 deletions.
74 changes: 74 additions & 0 deletions packages/typescript/rules-snapshot.json
@@ -1,21 +1,66 @@
{
"@typescript-eslint/adjacent-overload-signatures": "error",
"@typescript-eslint/array-type": "error",
"@typescript-eslint/await-thenable": "error",
"@typescript-eslint/ban-ts-comment": "error",
"@typescript-eslint/ban-types": "error",
"@typescript-eslint/consistent-type-assertions": "error",
"@typescript-eslint/consistent-type-definitions": ["error", "type"],
"@typescript-eslint/consistent-type-exports": "error",
"@typescript-eslint/default-param-last": "error",
"@typescript-eslint/naming-convention": [
"error",
{
"selector": "default",
"format": ["camelCase"],
"leadingUnderscore": "allow",
"trailingUnderscore": "forbid"
},
{
"selector": "enumMember",
"format": ["PascalCase"]
},
{
"selector": "interface",
"format": ["PascalCase"],
"custom": {
"regex": "^I[A-Z]",
"match": false
}
},
{
"selector": "objectLiteralMethod",
"format": ["camelCase", "PascalCase", "UPPER_CASE"]
},
{
"selector": "objectLiteralProperty",
"format": ["camelCase", "PascalCase", "UPPER_CASE"]
},
{
"selector": "typeLike",
"format": ["PascalCase"]
},
{
"selector": "variable",
"format": ["camelCase", "UPPER_CASE", "PascalCase"],
"leadingUnderscore": "allow"
}
],
"@typescript-eslint/no-array-constructor": "error",
"@typescript-eslint/no-dupe-class-members": "error",
"@typescript-eslint/no-empty-function": "error",
"@typescript-eslint/no-empty-interface": "error",
"@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/no-extra-non-null-assertion": "error",
"@typescript-eslint/no-extra-semi": "off",
"@typescript-eslint/no-floating-promises": "error",
"@typescript-eslint/no-for-in-array": "error",
"@typescript-eslint/no-implied-eval": "error",
"@typescript-eslint/no-inferrable-types": "error",
"@typescript-eslint/no-loss-of-precision": "error",
"@typescript-eslint/no-meaningless-void-operator": "error",
"@typescript-eslint/no-misused-new": "error",
"@typescript-eslint/no-misused-promises": "error",
"@typescript-eslint/no-namespace": [
"error",
{
Expand All @@ -33,7 +78,17 @@
}
],
"@typescript-eslint/no-this-alias": "error",
"@typescript-eslint/no-throw-literal": "error",
"@typescript-eslint/no-unnecessary-boolean-literal-compare": "error",
"@typescript-eslint/no-unnecessary-qualifier": "error",
"@typescript-eslint/no-unnecessary-type-arguments": "error",
"@typescript-eslint/no-unnecessary-type-assertion": "error",
"@typescript-eslint/no-unnecessary-type-constraint": "error",
"@typescript-eslint/no-unsafe-argument": "off",
"@typescript-eslint/no-unsafe-assignment": "off",
"@typescript-eslint/no-unsafe-call": "off",
"@typescript-eslint/no-unsafe-member-access": "off",
"@typescript-eslint/no-unsafe-return": "off",
"@typescript-eslint/no-unused-expressions": [
"error",
{
Expand Down Expand Up @@ -61,9 +116,26 @@
"@typescript-eslint/prefer-as-const": "error",
"@typescript-eslint/prefer-for-of": "error",
"@typescript-eslint/prefer-function-type": "error",
"@typescript-eslint/prefer-includes": "error",
"@typescript-eslint/prefer-namespace-keyword": "error",
"@typescript-eslint/prefer-nullish-coalescing": "error",
"@typescript-eslint/prefer-optional-chain": "error",
"@typescript-eslint/prefer-readonly": "error",
"@typescript-eslint/prefer-reduce-type-parameter": "error",
"@typescript-eslint/prefer-string-starts-ends-with": "error",
"@typescript-eslint/promise-function-async": "error",
"@typescript-eslint/require-await": "error",
"@typescript-eslint/restrict-plus-operands": "error",
"@typescript-eslint/restrict-template-expressions": [
"error",
{
"allowBoolean": true,
"allowNumber": true
}
],
"@typescript-eslint/switch-exhaustiveness-check": "error",
"@typescript-eslint/triple-slash-reference": "error",
"@typescript-eslint/unbound-method": "error",
"@typescript-eslint/unified-signatures": "error",
"constructor-super": "off",
"default-param-last": "off",
Expand All @@ -85,6 +157,7 @@
"no-empty-function": "off",
"no-extra-semi": "off",
"no-func-assign": "off",
"no-implied-eval": "off",
"no-import-assign": "off",
"no-loss-of-precision": "off",
"no-new-symbol": "off",
Expand Down Expand Up @@ -112,5 +185,6 @@
"prefer-const": "error",
"prefer-rest-params": "error",
"prefer-spread": "error",
"require-await": "off",
"valid-typeof": "off"
}
2 changes: 2 additions & 0 deletions packages/typescript/src/__test__/dummy.ts
@@ -0,0 +1,2 @@
// This file is only used to test the config.
console.log('Hello, world!');
75 changes: 74 additions & 1 deletion packages/typescript/src/index.js
Expand Up @@ -15,12 +15,19 @@ module.exports = {
// (not pre-release) here: https://github.com/tc39/ecma262/releases
ecmaVersion: 2020,
sourceType: 'module',

// This enables support for linting rules that require type information. We
// assume that the project has a `tsconfig.json` file in the directory where
// ESLint is being run.
tsconfigRootDir: process.cwd(),
project: ['./tsconfig.json'],
},

plugins: ['@typescript-eslint', 'jsdoc'],

extends: [
'plugin:@typescript-eslint/recommended',
'plugin:@typescript-eslint/recommended-requiring-type-checking',
'plugin:import/typescript',
],

Expand Down Expand Up @@ -59,14 +66,80 @@ module.exports = {
},
],

// Recommended rules that require type information
'@typescript-eslint/no-unsafe-argument': 'off',
'@typescript-eslint/no-unsafe-assignment': 'off',
'@typescript-eslint/no-unsafe-call': 'off',
'@typescript-eslint/no-unsafe-member-access': 'off',
'@typescript-eslint/no-unsafe-return': 'off',

// Our rules that require type information
'@typescript-eslint/consistent-type-exports': 'error',
'@typescript-eslint/naming-convention': [
'error',
{
selector: 'default',
format: ['camelCase'],
leadingUnderscore: 'allow',
trailingUnderscore: 'forbid',
},
{
selector: 'enumMember',
format: ['PascalCase'],
},
{
selector: 'interface',
format: ['PascalCase'],
custom: {
regex: '^I[A-Z]',
match: false,
},
},
{
selector: 'objectLiteralMethod',
format: ['camelCase', 'PascalCase', 'UPPER_CASE'],
},
{
selector: 'objectLiteralProperty',
format: ['camelCase', 'PascalCase', 'UPPER_CASE'],
},
{
selector: 'typeLike',
format: ['PascalCase'],
},
{
selector: 'variable',
format: ['camelCase', 'UPPER_CASE', 'PascalCase'],
leadingUnderscore: 'allow',
},
],
'@typescript-eslint/no-meaningless-void-operator': 'error',
'@typescript-eslint/no-unnecessary-boolean-literal-compare': 'error',
'@typescript-eslint/no-unnecessary-qualifier': 'error',
'@typescript-eslint/no-unnecessary-type-arguments': 'error',
'@typescript-eslint/prefer-includes': 'error',
'@typescript-eslint/prefer-nullish-coalescing': 'error',
'@typescript-eslint/prefer-readonly': 'error',
'@typescript-eslint/prefer-reduce-type-parameter': 'error',
'@typescript-eslint/prefer-string-starts-ends-with': 'error',
'@typescript-eslint/promise-function-async': 'error',
'@typescript-eslint/restrict-template-expressions': [
'error',
{
allowBoolean: true,
allowNumber: true,
},
],
'@typescript-eslint/switch-exhaustiveness-check': 'error',

'default-param-last': 'off',
'@typescript-eslint/default-param-last': 'error',

'no-shadow': 'off',
'@typescript-eslint/no-shadow': ['error', { builtinGlobals: true }],

'no-throw-literal': 'off',
// '@typescript-eslint/no-throw-literal' is left disabled because it requires type information
'@typescript-eslint/no-throw-literal': 'error',

'no-unused-expressions': 'off',
'@typescript-eslint/no-unused-expressions': [
Expand Down
12 changes: 10 additions & 2 deletions packages/typescript/src/index.test.js
@@ -1,20 +1,28 @@
const { ESLint } = require('eslint');
const { resolve } = require('path');

const config = require('.');

describe('index', () => {
it('is a valid ESLint config', async () => {
const api = new ESLint({
baseConfig: config,
useEslintrc: false,
overrideConfig: {
env: {
node: true,
},
parserOptions: {
tsconfigRootDir: resolve(__dirname, '..'),
project: 'tsconfig.json',
},
},
useEslintrc: false,
});

const result = await api.lintText(`console.log('Hello, world!');\n`);
// In order to test rules that require type information, we need to actually
// compile the file with TypeScript, so rather than using `api.lintText()`,
// we use `api.lintFiles()` and pass in a file that we know will pass.
const result = await api.lintFiles(resolve(__dirname, '__test__/dummy.ts'));

expect(result[0].messages).toStrictEqual([]);
expect(result[0].warningCount).toBe(0);
Expand Down
3 changes: 3 additions & 0 deletions packages/typescript/tsconfig.json
@@ -0,0 +1,3 @@
{
"include": ["src"]
}

0 comments on commit 32abef3

Please sign in to comment.