@wise/eslint-config
Version:
A modular ESLint config used at Wise.
183 lines (125 loc) • 6.25 kB
Markdown
A modular ESLint config used at [Wise](https://wise.com/).
[](https://www.npmjs.com/package/@wise/eslint-config)
1. Install the package as a dev dependency along with ESLint:
```sh
pnpm add --save-dev @wise/eslint-config
```
2. Extend your ESLint configuration as follows:
```js
// .eslint.config.js
import baseStrict from '@wise/eslint-config/base-strict';
import react from '@wise/eslint-config/react';
import next from '@wise/eslint-config/next';
import jest from '@wise/eslint-config/jest';
import cypress from '@wise/eslint-config/cypress';
import storybook from '@wise/eslint-config/storybook';
import testingLibrary from '@wise/eslint-config/testing-library-react';
export default [
/* Recommended for all projects, includes TypeScript rules. */
...baseStrict, // you can import from '@wise/esltin-config/base' instead
/* Uncomment lines in the order below as you adopt each technology */
// ...react,
// ...next,
// ...jest,
// ...cypress,
// ...storybook,
// ...testingLibrary,
];
```
3. If you’re using a monorepo with TypeScript, please set `parserOptions.projectService = true` [as per the docs of typescript-eslint](https://typescript-eslint.io/troubleshooting/typed-linting/monorepos/).
Set up your package.json scripts to run the linting on the CLI. We recommend adhering to [ESLint’s package.json conventions](https://eslint.org/docs/latest/contribute/package-json-conventions) for naming scripts.
```jsonc
// package.json
{
"scripts": {
/* TypeScript-specific logic may be enabled as hinted by comments below */
"lint": "pnpm run lint:js+ts && pnpm run lint:format", // && pnpm run lint:types
"lint:js+ts": "eslint '**/*.{js,jsx,mjs,cjs,ts,tsx,mts,cts}'",
"lint:format": "prettier \"**/*\" --check --ignore-unknown",
// "lint:types": "tsc --noEmit",
"lint:fix": "pnpm run lint:fix:js+ts && pnpm run lint:fix:format",
"lint:fix:js+ts": "pnpm run lint:js+ts --fix",
"lint:fix:format": "prettier \"**/*\" --write --ignore-unknown",
},
}
```
Stylistic linting rules which may conflict with Prettier are turned off.
We encourage developers to **use Prettier’s opinionated defaults** with no additional configuration.
1. Install packages as follows:
```sh
pnpm add --save-dev husky nano-staged
```
2. Configure scripts to be run on staged files:
```jsonc
// package.json
"nano-staged": {
"*": "prettier --write --ignore-unknown",
"*.{js,jsx,mjs,cjs,ts,tsx,mts,cts}": "eslint --fix",
}
```
3. Configure git hooks via Husky:
```sh
pnpm exec husky
echo "pnpm exec nano-staged" > .husky/pre-commit
npm pkg set scripts.prepare="husky || cd ."
```
_The `|| cd .` part sets the exit code to zero [in a cross-platform manner](https://stackoverflow.com/a/62817845) when `husky` isn’t found, e.g. when `devDependencies` aren’t installed._
Extend your editor configuration as follows:
```jsonc
// .vscode/settings.json
{
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit",
},
}
```
If you think a rule should be added or changed, please create a pull request. Releases are managed via [Changesets](https://github.com/changesets/changesets) and follow [Semantic Versioning](https://semver.org/) conventions.
**Rules of our configs shouldn’t be turned off or overridden in general.** When encountering a false-positive, please disable it via `eslint-disable-next-line` or `eslint-disable` and consider filing an issue to the Web Guild.
The first time you integrate with the config, you might get a lot of import issues.
```
1:1 warning Run autofix to sort these imports! simple-import-sort/imports
```
This error is auto-fixable using the `--fix` option.
When trying to import from a `.d.ts` file, `import type` should be used over `import`, e.g.:
```diff
- import { AlertType } from "@transferwise/components/build/types/alert/Alert";
+ import type { AlertType } from "@transferwise/components/build/types/alert/Alert";
```
Furthermore, setting [`verbatimModuleSyntax` in TSConfig](https://www.typescriptlang.org/tsconfig#verbatimModuleSyntax) is recommended to avoid these issues and deal with side-effects explicitly.
When using multiple configuration files in `tsconfig.json`, e.g. `extends: ["array", "of", "tsconfigs"]`, the following error may occur:
> TypeError: The "path" argument must be of type string. Received an instance of Array
This happens because [eslint-import-resolver-typescript](https://github.com/import-js/eslint-import-resolver-typescript) doesn’t support the array `extends` syntax introduced by TypeScript 5.
Please don’t extend from multiple TSConfigs at this time.
When linting JavaScript without types, the following error may occur:
> You appear to be using a native ECMAScript module configuration file, which is only supported when running Babel asynchronously
This happens if your [Babel configuration](https://babeljs.io/docs/configuration#javascript-configuration-files) uses ECMAScript module syntax. By migrating to JSON or using CommonJS, the issue can be mitigated, e.g.:
```diff
// babel.config.js
- export default { /* … */ };
+ module.exports = { /* … */ };
```
Sometimes, if you integrate, you might see an error similar to this
```
Oops! Something went wrong! :(
ESLint: 9.13.0
ConfigError: Config (unnamed): Key "plugins": Cannot redefine plugin "import".
...
```
Most of the time, removing the offending plugin (in this case, `import`) in your config file should solve the issue.
What this means is that the said plugin is already imported by a previous config. Importing them again will cause the issue.