Stylish ESLint configuration for Front-end Engineers.
Requirements:
eslint: v9 or later@eslint/js: v9 or latereslint-plugin-import: v2 or latereslint-plugin-jsx-a11y: v6 or latereslint-plugin-react: v7 or latereslint-plugin-react-hooks: v5 or latereslint-plugin-react-you-might-not-need-an-effect: v0.7.0 or latertypescript-eslint: v8 or later (if you use TypeScript)eslint-import-resolver-typescript: v3 or later (if you use TypeScript)
pnpm add -D \
eslint-config-stylish \
eslint @eslint/js \
eslint-plugin-import \
eslint-plugin-jsx-a11y \
eslint-plugin-react \
eslint-plugin-react-hooks \
eslint-plugin-react-you-might-not-need-an-effect \
typescript-eslint \
eslint-import-resolver-typescript- Base: Customized ESLint rules, import/export rules
- React: Customized rules for React, JSX a11y
- TypeScript: Adds TypeScript-specific linting rules and configurations.
set up your eslint.config.js file like this
import { defineConfig } from 'eslint/config';
import stylish from 'eslint-config-stylish';
export default defineConfig([
{
files: ['**/*.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
extends: [stylish],
},
/* */
]);import { defineConfig } from 'eslint/config';
import stylishReact from 'eslint-config-stylish/react';
import stylishReactHooks from 'eslint-config-stylish/react-hooks';
export default defineConfig([
{
files: ['**/*.{js,jsx,tsx}'],
extends: [stylishReact, stylishReactHooks],
},
{
files: ['**/use*.ts'],
extends: [stylishReactHooks],
},
/* */
]);import { defineConfig } from 'eslint/config';
import stylishTypeScript from 'eslint-config-stylish/typescript';
export default defineConfig([
{
files: ['**/*.{ts,mts,cts,tsx}'],
languageOptions: {
parserOptions: {
project: './tsconfig.json',
ecmaFeatures: {
jsx: true,
},
ecmaVersion: 12,
sourceType: 'module',
},
},
extends: [stylishTypeScript],
},
/* */
]);js: recommendimport: recommendedreact: recommendedjsx-a11y: recommendedreact-you-might-not-need-an-effect: recommended@typescript-eslintstrict type checked
array-callback-return:error(setallowImplicittotrue)block-scoped-var:errorclass-methods-use-this:errorconsistent-return:errorcurly:error(multi,consistent)default-case:error(Ignore with skip default comment)default-case-last:errordefault-param-last:erroreqeqeq:error- always use
===and!== - ignore
null
- always use
grouped-accessor-pairs:errorguard-for-in:errormax-classes-per-file:error(1 class per file)no-alert:warnno-array-constructor:errorno-await-in-loop:errorno-caller:errorno-console:warnno-constructor-return:errorno-div-regex:errorno-else-return:error(disallowelse ifblocks after a return too)no-eval:errorno-extend-native:errorno-extra-bind:errorno-extra-label:errorno-implied-eval:errorno-inner-declarations:errorno-iterator:errorno-label-var:errorno-labels:errorno-lone-blocks:errorno-loop-func:errorno-new:errorno-new-func:errorno-new-wrappers:errorno-object-constructor:errorno-octal-escape:errorno-param-reassign:error(ignore to reducer, contexts, request, response, state)no-promise-executor-return:errorno-proto:errorno-redeclare:errorno-restricted-exports:error(disallowdefault,thenexports)no-restricted-globals:error(isFinite,isNaN)no-restricted-properties:error(isFinite,isNaN,__defineGetter__,__defineSetter__)no-restricted-syntax:error(WithStatement,LabeledStatement)no-return-assign:error(disallow all assignments)no-script-url:errorno-self-compare:errorno-sequences:errorno-shadow:errorno-template-curly-in-string:errorno-throw-literal:errorno-undef-init:errorno-unreachable-loop:errorno-unused-expressions:errorno-unused-labels:errorno-unused-vars:error- ignore after used arguments
- ignore pattern:
/^_/ - ignore rest siblings
no-use-before-define:errorno-useless-constructor:errorno-var:errorno-void:error(allows the void operator as a statement)prefer-promise-reject-errors:error(allow empty reject)prefer-rest-params:errorprefer-spread:errorradix:errorsymbol-description:errorvalid-typeof:error(require string literals)
arrow-body-style:errorcamelcase:error- does not check property names, ES2015 imports, global variables
- allows
unstable_andexperimental_prefixes
dot-notation:errorfunc-names:warn(as needed)new-cap:error- allows uppercase-started functions to be called without new operators.
- disables checks on object properties
no-continue:errorno-empty-function:error(allowarrowFunctions,functions,methods)no-lonely-if:errorno-multi-assign:errorno-multi-str:errorno-nested-ternary:errorno-plusplus:error(allows inforloops)no-unneeded-ternary:error(disallows the conditional expression as a default assignment pattern too)no-useless-computed-key:errorno-useless-concat:errorno-useless-rename:errorno-useless-return:errorobject-shorthand:error(ignore constructors, avoid quotes)one-var:error(requires multiple variable declarations per scope)operator-assignment:errorprefer-arrow-callback:errorprefer-const:error(ignore variables that are read between the declaration and the first assignment)prefer-destructuring:errorVariableDeclarator: setfalseto array,trueto objectAssignmentExpression: settrueto array,falseto object- set
truetoenforceForRenamedProperties
prefer-exponentiation-operator:errorprefer-numeric-literals:errorprefer-object-spread:errorprefer-regex-literals:error(disallow redundant wrapping)prefer-template:errorunicode-bom:error(never)vars-on-top:erroryoda:error
import/export:offimport/extensions:error- disallow extensions after
js,jsx,ts, andtsx ignorePackagesis set totrue
- disallow extensions after
import/newline-after-import:errorimport/no-cycle:off(due to performance issues)import/no-extraneous-dependencies:error- set
devDependenciesfor testing (default) - project-specific overrides may be required
- set
import/no-self-import:errorimport/no-unresolved:offimport/order:error- sort by the groups
type,builtin,external,internal,parent,sibling,index, - set
newlines-betweentoalways-and-inside-groups - in TypeScript, add the
@/components/**pattern (after theinternalgroup)
- sort by the groups
import/prefer-default-export:error
react/button-has-type:errorreact/destructuring-assignment:errorreact/display-name:offreact/function-component-definition:errornamedComponentsset toarrow-function,function-declarationunnamedComponentsset toarrow-function
react/jsx-curly-brace-presence:error(neverforprops,children)react/jsx-curly-newline:error(consistentformultiline,singleline)react/jsx-equals-spacing:errorreact/jsx-filename-extension:warn(.js,.jsx,.tsx)react/jsx-first-prop-new-line:errorreact/jsx-fragments:error(syntaxmode)react/jsx-indent:error(2 spaces indentation)react/jsx-no-constructed-context-values:errorreact/jsx-no-script-url:error(also applies toLinkcomponent)react/jsx-no-target-blank:errorreact/jsx-no-useless-fragment:errorreact/jsx-one-expression-per-line:error(allows single child)react/jsx-props-no-multi-spaces:errorreact/jsx-tag-spacing:error(beforeSelfClosingonlyalwaysEverything elsenever)react/jsx-wrap-multilines:error(all properties are set toparens-new-line)react/no-invalid-html-attribute:errorreact/no-namespace:errorreact/no-this-in-sfc:errorreact/no-unstable-nested-components:errorreact/no-unused-prop-types:errorreact/prop-types:off(almost all projects use the TypeScript)react/require-default-propsoff(same as above)react/self-closing-comp:errorreact/style-prop-object:errorreact/void-dom-elements-no-children:error
react-hooks/rules-of-hooks:errorreact-hooks/exhaustive-deps:warn
You Might Not Need an Effect all rules from the recommended configuration are enabled
jsx-a11y/anchor-has-content:error(includeLinkcomponent)jsx-a11y/aria-role:error(apply non-DOM)jsx-a11y/control-has-associated-label:error(overridedepthto 5)jsx-a11y/label-has-associated-control:error- add
Labelcomponent tolabelComponentsoption - add
Inputcomponent tocontrolComponentsoption - set
asserttoeither - set
depthto the maximum value(25)
- add
jsx-a11y/no-autofocus:error(apply non-DOM)
@typescript-eslint/class-methods-use-this:error(extendsclass-methods-use-this)@typescript-eslint/consistent-return:error(extendsconsistent-return)@typescript-eslint/default-param-last:error(extendsdefault-param-last)@typescript-eslint/no-base-to-string:error(ignore fromError,RegExp,URL,URLSearchParams,ReactNode,ArrayBuffer)@typescript-eslint/no-confusing-void-expression:error(ignore "shorthand" arrow functions)@typescript-eslint/no-empty-object-type:error(allow interfaces with single extends)@typescript-eslint/no-floating-promises:error(ignorevoidexpressions and IIFEs)@typescript-eslint/no-loop-func:error(extendsno-loop-func)@typescript-eslint/no-misused-promises:error(ignore when a Promise is returned from a function typed as returningvoid)@typescript-eslint/no-shadow:error(extendsno-shadow)@typescript-eslint/no-unused-vars:error(extendsno-unused-vars)@typescript-eslint/no-use-before-define:error(extendsno-use-before-define)@typescript-eslint/no-useless-constructor:error(extendsno-useless-constructor)@typescript-eslint/only-throw-error:error(extendsno-throw-literal)@typescript-eslint/prefer-destructuring:error(extendsprefer-destructuring)@typescript-eslint/prefer-promise-reject-errors:error(allow throwing values typed asunknown)@typescript-eslint/require-await:off@typescript-eslint/restrict-template-expressions:error(allow number)@typescript-eslint/unbound-method:error(ignore static)
@typescript-eslint/adjacent-overload-signatures:error@typescript-eslint/array-type:error@typescript-eslint/ban-tslint-comment:error@typescript-eslint/consistent-generic-constructors:error@typescript-eslint/consistent-indexed-object-style:error@typescript-eslint/consistent-type-assertions:error@typescript-eslint/dot-notation:error(extendsdot-notation)@typescript-eslint/no-confusing-non-null-assertion:error@typescript-eslint/no-empty-function:error(extendsno-empty-function)@typescript-eslint/no-inferrable-types:error@typescript-eslint/prefer-find:error@typescript-eslint/prefer-for-of:error@typescript-eslint/prefer-function-type:error@typescript-eslint/prefer-includes:error@typescript-eslint/prefer-nullish-coalescing:error@typescript-eslint/prefer-optional-chain:error@typescript-eslint/prefer-regexp-exec:error@typescript-eslint/prefer-string-starts-ends-with:error