# @beyondessential/eslint-config-ts

## TypeScript/React.js style guide as as shareable ESLint configuration

This package defines [Beyond Essential System](https://beyondessential.com.au/)'s style guide for TypeScript/React.js projects. It extends our [JavaScript/React.js style guide](https://github.com/beyondessential/eslint-config-beyondessential/blob/master/packages/js/README.md), with additional TypeScript-specific rules.

## Installation

```sh
yarn add -D @beyondessential/eslint-config-ts
```

## Usage

You need to extend this package in your [ESLint configuration](https://eslint.org/docs/user-guide/configuring):

```json
{
  "extends": "@beyondessential/ts"
}
```

⚠️ If you use a TS configuration file other than the default (`tsconfig.json` under the project's root), you need to specify its path:

```json
{
  "parserOptions": {
    "project": "ts/tsconfig.dev.json"
  }
}
```

⚠️ If you get the following error:

> Configuration for rule "@typescript-eslint/indent" is invalid

it is a known [eslint-config-airbnb-typescript issue](https://github.com/iamturns/eslint-config-airbnb-typescript/issues/98#issuecomment-665317214), see that link for possible solutions.

## Maintenance

Please be mindful of this package's twin sibling, [@beyondessential/eslint-config-ts](packages/ts): you may want to reflect any common rule/dependency updates in that package too.

## Publishing

1. Checkout the latest code: `git fetch && git checkout master`
2. Commit your changes in a new branch
3. ⚠️ Don't forget to also update the package version: `npm version # < patch || minor || major >`
4. Create a pull request against `master`

After your PR is approved and merged:

```sh
git fetch && git checkout master && git pull
npm login
npm publish --access public
```

## Style guide

This style guide is a combination of:

- The [Typescript port](https://www.npmjs.com/package/eslint-config-airbnb-typescript) of the [Airbnb Style Guide](https://github.com/airbnb/javascript). with some changes
- The recommended rules from [@typescript-eslint/eslint-plugin](https://www.npmjs.com/package/eslint-plugin-jest#rules), with some changes

### Changes

| Rule                                                                                                                                                                                        | Airbnb                               | BES                     | Comment                                                                                                                                                                                                                                                                                           |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------ | ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [@typescript-eslint/explicit-function-return-type](https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/explicit-function-return-type.md)   | error                                | off                     | TypeScript can accurately infer return types. Explicit return types should be used only when they use a project-specific type which is not inferred automatically                                                                                                                                 |
| [@typescript-eslint/explicit-module-boundary-types](https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/explicit-module-boundary-types.md) | error                                | off                     | Similarly to `@typescript-eslint/explicit-function-return-type`                                                                                                                                                                                                                                   |
| [@typescript-eslint/no-use-before-define](https://eslint.org/docs/rules/no-use-before-define)                                                                                               | error                                | off                     |
| [@typescript-eslint/comma-dangle](https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/comma-dangle.md)                                     | error                                | off                     | Prettier and eslint seem to have conflicting errors on when to apply this rule, so disabling eslint in favor of prettier                                                                                                                                                                          |
| [@typescript-eslint/no-empty-interface](https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-empty-interface.md)                         | error                                | Allow single extends    | In some circumstances it can be useful to define a type that extends a single generic interface with concrete types                                                                                                                                                                               |
| [@typescript-eslint/lines-between-class-members](https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/lines-between-class-members.md)       | error                                | off                     | This rule leads to extraneously long classes in some cases. Prefer to leave it up to developer discretion                                                                                                                                                                                         |
| [@typescript-eslint/explicit-member-accessibility](https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/explicit-member-accessibility.md)   | off                                  | Require explicit access | Enforcing explicit accessibility modifiers helps encourage better encapsulation practices                                                                                                                                                                                                         |
| [class-methods-use-this](https://eslint.org/docs/rules/class-methods-use-this)                                                                                                              | error                                | off                     | This rule was made to encourage the usage of static methods where possible. However, there are valid reasons to not use a static method, even if `this` is not required (eg testability, inheritance, using functionality via the instance rather than the class).                                |
| [import/order](https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/order.md)                                                                                           | error                                | warn                    |                                                                                                                                                                                                                                                                                                   |
| [import/prefer-default-export](https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/prefer-default-export.md)                                                           | error                                | off                     |                                                                                                                                                                                                                                                                                                   |
| [no-await-in-loop](https://eslint.org/docs/rules/no-await-in-loop)                                                                                                                          | error                                | off                     | This is a common syntax for async operations that must be performed serially.                                                                                                                                                                                                                     |
| [no-continue](https://eslint.org/docs/rules/no-continue)                                                                                                                                    | error                                | off                     | In most cases it is preferable to break our functions into smaller ones than use `continue`. However, sometimes it serves as a compromise between performance and readability. Also, it is useful in refactoring big functions in legacy code.                                                    |
| [no-plusplus](https://eslint.org/docs/rules/no-plusplus)                                                                                                                                    | error                                | off                     | A standard in `for` loops, which we allow.                                                                                                                                                                                                                                                        |
| [no-prototype-builtins](https://eslint.org/docs/rules/no-prototype-builtins)                                                                                                                | error                                | off                     |                                                                                                                                                                                                                                                                                                   |
| [no-restricted-globals](https://eslint.org/docs/rules/no-restricted-globals)                                                                                                                | error                                | off                     |                                                                                                                                                                                                                                                                                                   |
| [no-restricted-syntax](https://eslint.org/docs/rules/no-restricted-syntax)                                                                                                                  | Restrict `for...of` loops            | Allow `for...of` loops  |                                                                                                                                                                                                                                                                                                   |
| [radix](https://eslint.org/docs/rules/radix)                                                                                                                                                | error                                | off                     | In the vast majority of the cases we just use the default radix of `10`. There is one case where this rule would be useful: `array.map(parseInt)`, where `radix` will be wrongly set to the array index of each iteration. Unfortunately this rule's implementation does not cover this scenario. |
| [react/forbid-prop-types](https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/forbid-prop-types.md)                                                                     | Forbid `array`, `object`             | Allow `array`, `object` |                                                                                                                                                                                                                                                                                                   |
| [react/jsx-filename-extension](https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-filename-extension.md)                                                           | Allow only .jsx                      | off                     |                                                                                                                                                                                                                                                                                                   |
| [react/jsx-one-expression-per-line](https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-one-expression-per-line.md)                                                 | ['error', { allow: 'single-child' }] | off                     |                                                                                                                                                                                                                                                                                                   |
| [react/jsx-props-no-spreading](https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-props-no-spreading.md)                                                           | error                                | off                     |                                                                                                                                                                                                                                                                                                   |
| [react/no-did-update-set-state](https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-did-update-set-state.md)                                                         | error                                | off                     |                                                                                                                                                                                                                                                                                                   |

### Additions

#### Enforce [prettier](https://prettier.io/) formatting

Rule: `prettier/prettier: error`
Configuration:

```json
{
  "arrowParens": "avoid",
  "printWidth": 100,
  "singleQuote": true,
  "trailingComma": "all"
}
```
