eslint-config-connorjs v1.1.1
eslint-config-connorjs
My (@connorjs) preferred ESLint configuration. With ESLint flat config.
Use it directly (§ Install) or take inspiration from it (§ Rules and reasoning).
🛑 IMPORTANT
eslint-comments/require-description is the single most important rule to configure! Please use it.
🟢 Tip: I highly recommend eslint-plugin-unicorn, which my config uses.
Table of contents
Install
Add the dependency
npm i -D eslint-config-connorjsInclude the config in your ESLint flat config.
import connorjsConfig from "eslint-config-connorjs"; export default [ // earlier configuration ...connorjsConfig, // later ];
To learn more about ESLint flat config, check out the blog posts or the documentation.
Project structure
The lib directory contains the ESLint configuration files.
It groups them by “use case.”
A use case could represent an entire language (html or json for example) or a tool (react or vitest).
Splitting by use case helps to copy desired configuration or building a functional form of the ESLint config. (See Sheriff for an example of the functional form.)
Rules and reasoning
The remainder of the README discusses the rules, configurations, and plugins used and why I used them.
The 🔧 emoji indicates that configured rules are automatically fixable with --fix.
🟢 Tip: The source code has inline comments that may provide more detail.
Base rules
The base rules config apply to all file types.
Configures ESLint linter options.
- reportUnusedDisableDirectives to keep code clean and up to date.
Includes eslint-plugin-eslint-comments and enforces comment descriptions (eslint-comments/require-description) to document why the code should ignore a configured ESLint rule.
Includes eslint-config-prettier to turns off all rules that are unnecessary or might conflict with Prettier.
🔧 Enforces template literals (backtick strings) to allow easier change to interpolation with eslint/quotes.
Configures the global ignores.
JSON
The JSON config applies to all JSON files. It handles JSONC (JSON with comments) and JSONC-like files.
Configures jsonc-eslint-parser as the parser for the
.jsonand.jsoncfiles.It does not lint
package-lock.json.Includes eslint-plugin-jsonc and registers its
recommended-with-jsonandprettierrule sets.🔧 Configures sorting rules to standardize the order (no need to think or worry about the “best” order) and reduces merge conflicts. Feel free to
eslint-disableat call sites.Allows comments in JSONC and JSONC-like files (for example,
tsconfig.json).🔧 Configures an explicit sort order for
package.jsonkeys. See the code for details.🔷 Note: This overrides the previous jsonc/sort-keys configuration. You can configure specific sort orders for other files using similar logic.
JavaScript and TypeScript
The JS and TS config applies to all JS and
TS files: cjs,js,ts,tsx. The largest configuration set!
Configures language options.
ecmaVersion: latestbecause projects use bundlers or other build tools to transpile to target versions.Includes isomorphic globals (shared by node and the browser) via globals
Also see the @typescript-eslint/parser documentation
🔧 Configures sorting rules to standardize the order (no need to think or worry about the “best” order) and reduces merge conflicts. Feel free to
eslint-disableat call sites. They are case-insensitive.🔧 @typescript-eslint/member-ordering with required properties first
Includes @eslint/js
recommendedrule set.Includes eslint-plugin-sonarjs
recommendedrule set.Includes eslint-plugin-unicorn
recommendedrule set and configures additional rules from unicorn. Some specific call-outs follow.🔧 Configures an allow list for unicorn/prevent-abbreviations to allow some abbreviations. Example: Allow
props, which React commonly uses.🔧 Configures patterns for unicorn/string-content to enforce better string content. Example: Use unicode arrow
→instead of hyphen and greater than (->).The auto-fix feature makes this rule very useful. See the source code for a “smart quotes” pattern.
Uses typescript-eslint and includes its
recommended-type-checkedandstylistic-type-checkedrule sets.🔧 Configures @typescript-eslint/consistent-type-definitions to enforce using
typeinstead ofinterface(as the default).Interfaces use declaration merging, which I do not recommend as the default. See the Differences Between Type Aliases and Interfaces documentation.
🔧 Configures @typescript-eslint/no-non-null-assertion to require a comment via
eslint-disablewhen needed. It allows non-null assertions in test files.
Uses eslint-plugin-simple-import-sort and eslint-plugin-import to configure import rules. Some specific call-outs follow.
🔧 Includes
simple-import-sort/importsandsimple-import-sort/exportsto sort the imports and re-exports. See the Sort order docs.I recommend the default configuration instead of creating your own order.
Includes eslint-plugin-import
recommendedrule set.Configures import/no-default-export to disallow default exports.
I have experienced various issues resulting from default exports over the years, so I strongly recommend configuring this rule. You can always
eslint-disableat the call site when you need it and explain why (example: dynamic imports for React code-splitting point).- Naming exports leads to a stronger contract and can help refactoring.
- You can use
assyntax to rename named exports very easily, so the supposed benefit of “name default exports whatever you want” has little benefit in practice. - I want to add more of my reasons, so TODO!
The ESLint configuration opts-out known configuration files that require default exports (example: storybook files).
Configures import/no-anonymous-default-export to disallow anonymous default exports in the case that you
eslint-disabletheimport/no-default-exportrule.🔧 Uses @typescript-eslint/consistent-type-imports and import/consistent-type-specifier-style to enforce consistent usage of type imports.
We need both rules for best fix-it developer experience: one to add
typeand the other to fix the placement.
React
The react config applies to all typescript files (ts and tsx) and only makes sense to use in a React project.
Uses eslint-plugin-jsx-a11y and its
recommendedrule set.Uses eslint-plugin-react and its
recommendedandjsx-runtimerule sets.Uses eslint-plugin-react-hooks and its
recommendedrule set.Configures react/destructuring-assignment to disallow destructuring props. (Controversial, I know.)
I find it harder to update components that use destructuring. Plus I think it looks bad with inline types given TypeScript usage.
Configures react/forbid-component-props to disallow props. (Example:
styleto disallow inline styles.)🔧 Configures react/function-component-definition to enforce component definition consistency.
Uses “function declarations” for named components because they are the only way to support generics in TSX, so using it for consistency. Remember: This will auto-fix.
Uses “arrow functions” for unnamed components to emphasize unnamed and for nice lambda readability (example: pass to
map).🔧 Enables react/hook-use-state to enforce symmetric naming of the
useStatehook value and setter variables.🔧 Configures react/jsx-boolean-value and react/jsx-curly-brace-presence to enforce consistent JSX styles. See the code for details.
Configures the following rules to force a comment explaining the use case. While this may seem like extra work, it helps catch improper usage.
- react/jsx-no-leaked-render
- react/jsx-props-no-spreading
- react/no-array-index-key
- react/no-danger
HTML
The HTML config applies to all HTML files.
Uses html-eslint.
Includes the
recommendedruleset and accessibility and best practice oriented rules. See the code for details, but some specific call-outs follow.@html-eslint/id-naming-convention to enforce kebab case for
idnaming.@html-eslint/no-inline-styles to disallow inline styles, mostly for Content Security Policy (CSP) reasons.
Even if you allow
unsafe-inlinefor the CSP, this rule would also require explanations for using inline styles instead of CSS witheslint-disable.@html-eslint/no-skip-heading-levels to disallow skipping heading levels.
@html-eslint/no-target-blank to disallow usage of unsafe
target='_blank'.
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago