Skip to content

Commit

Permalink
[FEAT] Recommended config (typescript-eslint#261)
Browse files Browse the repository at this point in the history
Fixes typescript-eslint#144
Requires ~~typescript-eslint#259~~, ~~typescript-eslint#260~~.

- added a util to make it standardised and easier to add default config for a rule
- configured recommended based on typescript-eslint#144
  - purposely switched `recommended` prop to be `"error" | "warning" | false`
    - inside the eslint repo, it should be `true`. otherwise it's just a property that isn't used officially by eslint. It's truthy so `eslint-docs` still work.
  - changed recommended generator to accept `"error"`/`"warning"` for more configurability.
- adjusted default config of certain rules that didn't match our recommendations.
  • Loading branch information
bradzacher authored and JamesHenry committed Jan 18, 2019
1 parent 8229d06 commit 32753d1
Show file tree
Hide file tree
Showing 44 changed files with 709 additions and 209 deletions.
2 changes: 2 additions & 0 deletions packages/eslint-plugin-typescript/.prettierignore
@@ -1 +1,3 @@
node_modules
lib/configs/recommended.json
.vscode
8 changes: 8 additions & 0 deletions packages/eslint-plugin-typescript/.vscode/launch.json
Expand Up @@ -17,6 +17,14 @@
],
"console": "integratedTerminal",
"internalConsoleOptions": "neverOpen"
},
{
"type": "node",
"request": "launch",
"name": "update-recommended.js",
"args": [
"${workspaceFolder}/tools/update-recommended.js"
]
}
]
}
64 changes: 37 additions & 27 deletions packages/eslint-plugin-typescript/README.md
Expand Up @@ -26,7 +26,7 @@ $ npm install eslint-plugin-typescript --save-dev

## Usage

Add `eslint-plugin-typescript/parser` to the `parser` field and `typescript` to the plugins section of your `.eslintrc` configuration file. You can omit the `eslint-plugin-` prefix:
Add `eslint-plugin-typescript/parser` to the `parser` field and `typescript` to the plugins section of your `.eslintrc` configuration file:

```json
{
Expand All @@ -35,18 +35,28 @@ Add `eslint-plugin-typescript/parser` to the `parser` field and `typescript` to
}
```

Note: The plugin provides its own version of the `typescript-eslint-parser` via `eslint-plugin-typescript/parser`.
This helps us guarantee 100% compatibility between the plugin and the parser.

Then configure the rules you want to use under the rules section.

```json
{
"parser": "eslint-plugin-typescript/parser",
"plugins": ["typescript"],
"rules": {
"typescript/rule-name": "error"
}
}
```

Note: The plugin provides its own version of the `typescript-eslint-parser` via `eslint-plugin-typescript/parser`.
This guarantees 100% compatibility between the plugin and the parser.
You can also enable all the recommended rules at once. Add `plugin:typescript/recommended` in extends:

```json
{
"extends": ["plugin:typescript/recommended"]
}
```

## Supported Rules

Expand All @@ -58,38 +68,38 @@ This guarantees 100% compatibility between the plugin and the parser.
<!-- prettier-ignore -->
| Name | Description | :heavy_check_mark: | :wrench: |
| ---- | ----------- | ------------------ | -------- |
| [`typescript/adjacent-overload-signatures`](./docs/rules/adjacent-overload-signatures.md) | Require that member overloads be consecutive (`adjacent-overload-signatures` from TSLint) | | |
| [`typescript/array-type`](./docs/rules/array-type.md) | Requires using either `T[]` or `Array<T>` for arrays (`array-type` from TSLint) | | :wrench: |
| [`typescript/ban-types`](./docs/rules/ban-types.md) | Enforces that types will not to be used (`ban-types` from TSLint) | | :wrench: |
| [`typescript/camelcase`](./docs/rules/camelcase.md) | Enforce camelCase naming convention | | |
| [`typescript/adjacent-overload-signatures`](./docs/rules/adjacent-overload-signatures.md) | Require that member overloads be consecutive (`adjacent-overload-signatures` from TSLint) | :heavy_check_mark: | |
| [`typescript/array-type`](./docs/rules/array-type.md) | Requires using either `T[]` or `Array<T>` for arrays (`array-type` from TSLint) | :heavy_check_mark: | :wrench: |
| [`typescript/ban-types`](./docs/rules/ban-types.md) | Enforces that types will not to be used (`ban-types` from TSLint) | :heavy_check_mark: | :wrench: |
| [`typescript/camelcase`](./docs/rules/camelcase.md) | Enforce camelCase naming convention | :heavy_check_mark: | |
| [`typescript/class-name-casing`](./docs/rules/class-name-casing.md) | Require PascalCased class and interface names (`class-name` from TSLint) | :heavy_check_mark: | |
| [`typescript/explicit-function-return-type`](./docs/rules/explicit-function-return-type.md) | Require explicit return types on functions and class methods | | |
| [`typescript/explicit-member-accessibility`](./docs/rules/explicit-member-accessibility.md) | Require explicit accessibility modifiers on class properties and methods (`member-access` from TSLint) | | |
| [`typescript/explicit-function-return-type`](./docs/rules/explicit-function-return-type.md) | Require explicit return types on functions and class methods | :heavy_check_mark: | |
| [`typescript/explicit-member-accessibility`](./docs/rules/explicit-member-accessibility.md) | Require explicit accessibility modifiers on class properties and methods (`member-access` from TSLint) | :heavy_check_mark: | |
| [`typescript/generic-type-naming`](./docs/rules/generic-type-naming.md) | Enforces naming of generic type variables | | |
| [`typescript/indent`](./docs/rules/indent.md) | Enforce consistent indentation (`indent` from TSLint) | :heavy_check_mark: | :wrench: |
| [`typescript/interface-name-prefix`](./docs/rules/interface-name-prefix.md) | Require that interface names be prefixed with `I` (`interface-name` from TSLint) | | |
| [`typescript/member-delimiter-style`](./docs/rules/member-delimiter-style.md) | Require a specific member delimiter style for interfaces and type literals | | :wrench: |
| [`typescript/interface-name-prefix`](./docs/rules/interface-name-prefix.md) | Require that interface names be prefixed with `I` (`interface-name` from TSLint) | :heavy_check_mark: | |
| [`typescript/member-delimiter-style`](./docs/rules/member-delimiter-style.md) | Require a specific member delimiter style for interfaces and type literals | :heavy_check_mark: | :wrench: |
| [`typescript/member-naming`](./docs/rules/member-naming.md) | Enforces naming conventions for class members by visibility. | | |
| [`typescript/member-ordering`](./docs/rules/member-ordering.md) | Require a consistent member declaration order (`member-ordering` from TSLint) | | |
| [`typescript/no-angle-bracket-type-assertion`](./docs/rules/no-angle-bracket-type-assertion.md) | Enforces the use of `as Type` assertions instead of `<Type>` assertions (`no-angle-bracket-type-assertion` from TSLint) | | |
| [`typescript/no-array-constructor`](./docs/rules/no-array-constructor.md) | Disallow generic `Array` constructors | | :wrench: |
| [`typescript/no-empty-interface`](./docs/rules/no-empty-interface.md) | Disallow the declaration of empty interfaces (`no-empty-interface` from TSLint) | | |
| [`typescript/no-explicit-any`](./docs/rules/no-explicit-any.md) | Disallow usage of the `any` type (`no-any` from TSLint) | | |
| [`typescript/no-angle-bracket-type-assertion`](./docs/rules/no-angle-bracket-type-assertion.md) | Enforces the use of `as Type` assertions instead of `<Type>` assertions (`no-angle-bracket-type-assertion` from TSLint) | :heavy_check_mark: | |
| [`typescript/no-array-constructor`](./docs/rules/no-array-constructor.md) | Disallow generic `Array` constructors | :heavy_check_mark: | :wrench: |
| [`typescript/no-empty-interface`](./docs/rules/no-empty-interface.md) | Disallow the declaration of empty interfaces (`no-empty-interface` from TSLint) | :heavy_check_mark: | |
| [`typescript/no-explicit-any`](./docs/rules/no-explicit-any.md) | Disallow usage of the `any` type (`no-any` from TSLint) | :heavy_check_mark: | |
| [`typescript/no-extraneous-class`](./docs/rules/no-extraneous-class.md) | Forbids the use of classes as namespaces (`no-unnecessary-class` from TSLint) | | |
| [`typescript/no-inferrable-types`](./docs/rules/no-inferrable-types.md) | Disallows explicit type declarations for variables or parameters initialized to a number, string, or boolean. (`no-inferrable-types` from TSLint) | | :wrench: |
| [`typescript/no-misused-new`](./docs/rules/no-misused-new.md) | Enforce valid definition of `new` and `constructor`. (`no-misused-new` from TSLint) | | |
| [`typescript/no-namespace`](./docs/rules/no-namespace.md) | Disallow the use of custom TypeScript modules and namespaces (`no-namespace` from TSLint) | | |
| [`typescript/no-non-null-assertion`](./docs/rules/no-non-null-assertion.md) | Disallows non-null assertions using the `!` postfix operator (`no-non-null-assertion` from TSLint) | | |
| [`typescript/no-object-literal-type-assertion`](./docs/rules/no-object-literal-type-assertion.md) | Forbids an object literal to appear in a type assertion expression (`no-object-literal-type-assertion` from TSLint) | | |
| [`typescript/no-parameter-properties`](./docs/rules/no-parameter-properties.md) | Disallow the use of parameter properties in class constructors. (`no-parameter-properties` from TSLint) | | |
| [`typescript/no-inferrable-types`](./docs/rules/no-inferrable-types.md) | Disallows explicit type declarations for variables or parameters initialized to a number, string, or boolean. (`no-inferrable-types` from TSLint) | :heavy_check_mark: | :wrench: |
| [`typescript/no-misused-new`](./docs/rules/no-misused-new.md) | Enforce valid definition of `new` and `constructor`. (`no-misused-new` from TSLint) | :heavy_check_mark: | |
| [`typescript/no-namespace`](./docs/rules/no-namespace.md) | Disallow the use of custom TypeScript modules and namespaces (`no-namespace` from TSLint) | :heavy_check_mark: | |
| [`typescript/no-non-null-assertion`](./docs/rules/no-non-null-assertion.md) | Disallows non-null assertions using the `!` postfix operator (`no-non-null-assertion` from TSLint) | :heavy_check_mark: | |
| [`typescript/no-object-literal-type-assertion`](./docs/rules/no-object-literal-type-assertion.md) | Forbids an object literal to appear in a type assertion expression (`no-object-literal-type-assertion` from TSLint) | :heavy_check_mark: | |
| [`typescript/no-parameter-properties`](./docs/rules/no-parameter-properties.md) | Disallow the use of parameter properties in class constructors. (`no-parameter-properties` from TSLint) | :heavy_check_mark: | |
| [`typescript/no-this-alias`](./docs/rules/no-this-alias.md) | Disallow aliasing `this` (`no-this-assignment` from TSLint) | | |
| [`typescript/no-triple-slash-reference`](./docs/rules/no-triple-slash-reference.md) | Disallow `/// <reference path="" />` comments (`no-reference` from TSLint) | | |
| [`typescript/no-triple-slash-reference`](./docs/rules/no-triple-slash-reference.md) | Disallow `/// <reference path="" />` comments (`no-reference` from TSLint) | :heavy_check_mark: | |
| [`typescript/no-type-alias`](./docs/rules/no-type-alias.md) | Disallow the use of type aliases (`interface-over-type-literal` from TSLint) | | |
| [`typescript/no-unused-vars`](./docs/rules/no-unused-vars.md) | Disallow unused variables (`no-unused-variable` from TSLint) | :heavy_check_mark: | |
| [`typescript/no-use-before-define`](./docs/rules/no-use-before-define.md) | Disallow the use of variables before they are defined | | |
| [`typescript/no-var-requires`](./docs/rules/no-var-requires.md) | Disallows the use of require statements except in import statements (`no-var-requires` from TSLint) | | |
| [`typescript/prefer-interface`](./docs/rules/prefer-interface.md) | Prefer an interface declaration over a type literal (type T = { ... }) (`interface-over-type-literal` from TSLint) | | :wrench: |
| [`typescript/prefer-namespace-keyword`](./docs/rules/prefer-namespace-keyword.md) | Require the use of the `namespace` keyword instead of the `module` keyword to declare custom TypeScript modules. (`no-internal-module` from TSLint) | | :wrench: |
| [`typescript/type-annotation-spacing`](./docs/rules/type-annotation-spacing.md) | Require consistent spacing around type annotations (`typedef-whitespace` from TSLint) | | :wrench: |
| [`typescript/no-use-before-define`](./docs/rules/no-use-before-define.md) | Disallow the use of variables before they are defined | :heavy_check_mark: | |
| [`typescript/no-var-requires`](./docs/rules/no-var-requires.md) | Disallows the use of require statements except in import statements (`no-var-requires` from TSLint) | :heavy_check_mark: | |
| [`typescript/prefer-interface`](./docs/rules/prefer-interface.md) | Prefer an interface declaration over a type literal (type T = { ... }) (`interface-over-type-literal` from TSLint) | :heavy_check_mark: | :wrench: |
| [`typescript/prefer-namespace-keyword`](./docs/rules/prefer-namespace-keyword.md) | Require the use of the `namespace` keyword instead of the `module` keyword to declare custom TypeScript modules. (`no-internal-module` from TSLint) | :heavy_check_mark: | :wrench: |
| [`typescript/type-annotation-spacing`](./docs/rules/type-annotation-spacing.md) | Require consistent spacing around type annotations (`typedef-whitespace` from TSLint) | :heavy_check_mark: | :wrench: |

<!-- end rule list -->
4 changes: 2 additions & 2 deletions packages/eslint-plugin-typescript/docs/rules/ban-types.md
Expand Up @@ -37,12 +37,12 @@ class Foo<F = string> extends Bar<string> implements Baz<string> {
// report usages of the type using the default error message
"Foo": null,
// add a custom message to help explain why not to use it
// add a custom message to help explain why not to use it
"Bar": "Don't use bar!",
// add a custom message, AND tell the plugin how to fix it
"String": {
"message": "Use string instead",
"message": "Use string instead",
"fixWith": "string"
}
}
Expand Down
41 changes: 38 additions & 3 deletions packages/eslint-plugin-typescript/lib/configs/recommended.json
@@ -1,7 +1,42 @@
{
"parser": "eslint-plugin-typescript/parser",
"parserOptions": {
"sourceType": "module"
},
"plugins": [
"typescript"
],
"rules": {
"class-name-casing": "error",
"indent": "error",
"no-unused-vars": "error"
"typescript/adjacent-overload-signatures": "error",
"typescript/array-type": "error",
"typescript/ban-types": "error",
"camelcase": "off",
"typescript/camelcase": "error",
"typescript/class-name-casing": "error",
"typescript/explicit-function-return-type": "warning",
"typescript/explicit-member-accessibility": "error",
"indent": "off",
"typescript/indent": "error",
"typescript/interface-name-prefix": "error",
"typescript/member-delimiter-style": "error",
"typescript/no-angle-bracket-type-assertion": "error",
"no-array-constructor": "off",
"typescript/no-array-constructor": "error",
"typescript/no-empty-interface": "error",
"typescript/no-explicit-any": "warning",
"typescript/no-inferrable-types": "error",
"typescript/no-misused-new": "error",
"typescript/no-namespace": "error",
"typescript/no-non-null-assertion": "error",
"typescript/no-object-literal-type-assertion": "error",
"typescript/no-parameter-properties": "error",
"typescript/no-triple-slash-reference": "error",
"no-unused-vars": "off",
"typescript/no-unused-vars": "warning",
"typescript/no-use-before-define": "error",
"typescript/no-var-requires": "error",
"typescript/prefer-interface": "error",
"typescript/prefer-namespace-keyword": "error",
"typescript/type-annotation-spacing": "error"
}
}
Expand Up @@ -18,6 +18,7 @@ module.exports = {
category: "TypeScript",
extraDescription: [util.tslintRule("adjacent-overload-signatures")],
url: util.metaDocsUrl("adjacent-overload-signatures"),
recommended: "error",
},
schema: [],
messages: {
Expand Down
5 changes: 4 additions & 1 deletion packages/eslint-plugin-typescript/lib/rules/array-type.js
Expand Up @@ -78,6 +78,8 @@ function typeNeedsParentheses(node) {
// Rule Definition
//------------------------------------------------------------------------------

const defaultOptions = ["array"];

module.exports = {
meta: {
type: "suggestion",
Expand All @@ -86,6 +88,7 @@ module.exports = {
extraDescription: [util.tslintRule("array-type")],
category: "TypeScript",
url: util.metaDocsUrl("array-type"),
recommended: "error",
},
fixable: "code",
messages: {
Expand All @@ -105,7 +108,7 @@ module.exports = {
],
},
create(context) {
const option = context.options[0] || "array";
const option = util.applyDefault(defaultOptions, context.options)[0];
const sourceCode = context.getSourceCode();

/**
Expand Down
31 changes: 30 additions & 1 deletion packages/eslint-plugin-typescript/lib/rules/ban-types.js
Expand Up @@ -10,6 +10,33 @@ const util = require("../util");
// Rule Definition
//------------------------------------------------------------------------------

const defaultOptions = [
{
types: {
String: {
message: "Use string instead",
fixWith: "string",
},
Boolean: {
message: "Use boolean instead",
fixWith: "boolean",
},
Number: {
message: "Use number instead",
fixWith: "number",
},
Object: {
message: "Use Record<string, any> instead",
fixWith: "Record<string, any>",
},
Symbol: {
message: "Use symbol instead",
fixWith: "symbol",
},
},
},
];

module.exports = {
meta: {
type: "suggestion",
Expand All @@ -18,6 +45,7 @@ module.exports = {
extraDescription: [util.tslintRule("ban-types")],
category: "TypeScript",
url: util.metaDocsUrl("ban-types"),
recommended: "error",
},
fixable: "code",
messages: {
Expand Down Expand Up @@ -52,7 +80,8 @@ module.exports = {
},

create(context) {
const banedTypes = (context.options[0] || {}).types || {};
const banedTypes = util.applyDefault(defaultOptions, context.options)[0]
.types;

//----------------------------------------------------------------------
// Public
Expand Down
18 changes: 11 additions & 7 deletions packages/eslint-plugin-typescript/lib/rules/camelcase.js
Expand Up @@ -10,13 +10,21 @@ const util = require("../util");
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
const defaultOptions = [
{
allow: ["^UNSAFE_"],
ignoreDestructuring: false,
properties: "never",
},
];

/* eslint-disable eslint-plugin/require-meta-type */
module.exports = {
meta: Object.assign({}, baseRule.meta, {
docs: {
description: "Enforce camelCase naming convention",
url: util.metaDocsUrl("ban-types"),
recommended: "error",
},
}),

Expand All @@ -29,13 +37,9 @@ module.exports = {
"TSAbstractClassProperty",
];

const options = context.options[0] || {};
let properties = options.properties || "";
const allow = options.allow || [];

if (properties !== "always" && properties !== "never") {
properties = "always";
}
const options = util.applyDefault(defaultOptions, context.options)[0];
const properties = options.properties;
const allow = options.allow;

/**
* Checks if a string contains an underscore and isn't all upper-case
Expand Down
Expand Up @@ -18,9 +18,10 @@ module.exports = {
description: "Require PascalCased class and interface names",
extraDescription: [util.tslintRule("class-name")],
category: "Best Practices",
recommended: true,
url: util.metaDocsUrl("class-name-casing"),
recommended: "error",
},
schema: [],
},

create(context) {
Expand Down

0 comments on commit 32753d1

Please sign in to comment.