ESLint (.eslintrc.json/.cjs)

Note: generally, the stricter the better (also, I generally start out with the T3 Stack standard vs "Aaron's Personal Preference")

Notes & Setup

.json vs .cjs

The difference in the file formats for ESLint configuration—.eslintrc.json versus .eslintrc.cjs—stems from the way ESLint allows configurations to be defined and the specific needs or constraints of your project. Let's explore the key differences and reasons:

.eslintrc.json

  • Format: JSON format.

  • Usage: It's a static configuration file. It's straightforward and widely used for simpler configurations.

  • Limitation: Being JSON, it doesn't support comments or dynamic configuration logic. It's purely declarative.

.eslintrc.cjs

  • Format: CommonJS module (JavaScript).

  • Usage: This format is used when you need a more dynamic or complex configuration. It allows the use of JavaScript to define the config, enabling conditional configurations, variables, comments, and other JavaScript features.

  • Common in TypeScript Projects: Especially useful in TypeScript projects where you might need to reference TypeScript types or enums in your ESLint configuration, as seen in your file with /** @type {import("eslint").Linter.Config} */.

  • Required in Certain Environments: If you're working in a project that uses ES Modules extensively, you might need to use .cjs for configuration files to ensure they are interpreted as CommonJS modules, particularly in Node.js environments where ES Module support is enabled.

Specifics in Your .eslintrc.cjs Configuration:

  • Dynamic Features: Your configuration utilizes JavaScript features like comments and variables, which aren't possible in plain JSON.

  • TypeScript Integration: The @type comment indicates TypeScript type checking for the config object. This enhances the configuration process by providing type safety and autocompletion in compatible editors.

  • Customized Rules: It includes custom rules and settings that are more sophisticated than a typical JSON config might support, like setting up specific options for rules ("@typescript-eslint/no-unused-vars", for example).

Choosing the Right Format:

  • Project Complexity: If your project requires a complex, dynamic ESLint configuration, or if you need to include comments for clarity, .eslintrc.cjs is a better choice.

  • Simplicity and Standards: For simpler projects, or to adhere to more standard configurations, .eslintrc.json is sufficient and easier to manage.

Each format has its use case, and the choice largely depends on the specific needs of your project and your team's preferences. The .cjs format offers more flexibility at the cost of slightly increased complexity, which can be valuable in larger or more complex projects, particularly those using TypeScript.


Sample setup (from T3 Stack + some custom modifications)

/** @type {import("eslint").Linter.Config} */
const config = {
  parser: "@typescript-eslint/parser",
  parserOptions: {
    project: true,
  },
  plugins: ["@typescript-eslint"],
  extends: [
    "next/core-web-vitals",
    "plugin:@typescript-eslint/recommended-type-checked",
    "plugin:@typescript-eslint/stylistic-type-checked",
  ],
  rules: {
    // These opinionated rules are enabled in stylistic-type-checked above.
    // Feel free to reconfigure them to your own preference.
    "@typescript-eslint/array-type": "off",
    "@typescript-eslint/consistent-type-definitions": "off",

    // custom
    "@typescript-eslint/no-empty-interface": "off", // can have empty Props {} interface (e.g. starting new components)
    "@typescript-eslint/ban-ts-comment": "off", // can use ts-ignore
    "@typescript-eslint/ban-ts-ignore": "off", // can use ts-ignore

    "@typescript-eslint/consistent-type-imports": [
      "warn",
      {
        prefer: "type-imports",
        fixStyle: "inline-type-imports",
      },
    ],
    "@typescript-eslint/no-unused-vars": ["warn", { argsIgnorePattern: "^_" }],
    "@typescript-eslint/no-misused-promises": [
      2,
      {
        checksVoidReturn: { attributes: false },
      },
    ],
  },
};

module.exports = config;
Aaron's Personal Preference

...not sure yet, but here is a recommended setup by ChatGPT (with the condition of "preferring to be on the stricter side of type-checking and ensuring certain formats, for clarity, consistency, maintainability")

{
  "extends": [
    "eslint:recommended",
    "@typescript-eslint/recommended",
    "plugin:react/recommended"
  ],
  "env": {
    "browser": true,
    "node": true,
    "es6": true
  },
  "parser": "@typescript-eslint/parser",
  "parserOptions": {
    "ecmaVersion": 2020,
    "sourceType": "module",
    "ecmaFeatures": {
      "jsx": true
    }
  },
  "plugins": [
    "@typescript-eslint",
    "react"
  ],
  "rules": {
    "eqeqeq": ["error", "always"],
    "curly": "error",
    "complexity": ["warn", 10],
    "consistent-return": "error",
    "arrow-parens": ["error", "always"],
    "no-unused-vars": "warn",
    "no-console": "warn",
    "no-debugger": "warn",
    "no-trailing-spaces": "error",
    "no-use-before-define": "error",
    "prefer-const": "error",
    "quotes": ["error", "single", { "avoidEscape": true }],
    "semi": ["error", "always"],
    "indent": ["error", 2],
    "linebreak-style": ["error", "unix"],
    "eol-last": ["error", "always"],
    "array-callback-return": "warn",
    "no-multiple-empty-lines": ["error", { "max": 1 }],
    "@typescript-eslint/no-explicit-any": "warn",
    "react/jsx-uses-react": "off",
    "react/react-in-jsx-scope": "off"
  },
  "settings": {
    "react": {
      "version": "detect"
    }
  }
}

This configuration:

  • Extends from eslint:recommended, @typescript-eslint/recommended, and plugin:react/recommended to include a robust set of standard, TypeScript, and React rules.

  • Sets the environment to browser, Node.js, and ES6 for global variables.

  • Uses the TypeScript parser for ESLint and sets ECMAScript 2020 as the version, with JSX support.

  • Includes rules for equality checks, curly braces usage, complexity limits, consistent return statements, arrow function parentheses, usage of const, single quotes, semicolons, indentation, linebreak style, end-of-line characters, array callback returns, and limiting multiple empty lines.

  • Warns against unused variables, console statements, and the use of any in TypeScript, encouraging a stricter type-checking approach.

  • Disables some React-specific rules (jsx-uses-react and react-in-jsx-scope) that are not necessary with the latest React versions due to the new JSX transform.

Additional Options
  1. noUseBeforeDefine (No Use Before Define):

    • Description: Disallows the use of variables before they are defined.

    • Popular Use: "no-use-before-define": "error" to prevent reference errors caused by using a variable before it's declared.

  2. maxParams (Maximum Parameters in Function Definition):

    • Description: Enforces a maximum number of parameters in function definitions.

    • Popular Use: "max-params": ["warn", 3] to warn when a function has more than three parameters, promoting functions that are easier to understand and maintain.

  3. complexity (Cyclomatic Complexity):

    • Description: Enforces a maximum cyclomatic complexity allowed in a program.

    • Popular Use: "complexity": ["warn", 10] to warn about functions that are too complex, which might be hard to understand and maintain.

  4. noImplicitAny (No Implicit any Type in TypeScript):

    • Description: Disallows the use of the any type without explicit declaration in TypeScript.

    • Popular Use: "@typescript-eslint/no-explicit-any": "error" to ensure strict typing in TypeScript projects.

  5. consistent-return (Enforce Consistent Return):

    • Description: Enforces that functions either always or never specify return types.

    • Popular Use: "consistent-return": "error" to ensure that functions are clear about their return values.

  6. indent (Indentation):

    • Description: Enforces a specific indentation style.

    • Popular Use: "indent": ["error", 2] or "indent": ["error", "tab"] to enforce a consistent indentation style of either spaces or tabs.

  7. no-trailing-spaces (No Trailing Spaces):

    • Description: Disallows trailing whitespace at the end of lines.

    • Popular Use: "no-trailing-spaces": "error" to keep the codebase clean and avoid unnecessary whitespace.

  8. curly (Curly Brace Convention):

    • Description: Enforces consistent use of curly braces in control statements.

    • Popular Use: "curly": "error" to ensure that if, else if, else, for, while, and do statements are always block-scoped with curly braces, improving readability and reducing errors.

  9. linebreak-style (Linebreak Style):

    • Description: Enforces a consistent linebreak style.

    • Popular Use: "linebreak-style": ["error", "unix"] or "linebreak-style": ["error", "windows"] based on your development environment.

  10. quotes (Quotation Marks):

    • Description: Enforces the consistent use of either backticks, double, or single quotes.

    • Popular Use: "quotes": ["error", "single", { "avoidEscape": true }] to enforce single quotes but allow double quotes to avoid escaping.

  11. no-unused-vars (No Unused Variables):

    • Description: Disallows unused variables.

    • Popular Use: "no-unused-vars": ["warn"] to catch and clean up variables that are declared but not used.

  12. prefer-const (Prefer const):

    • Description: Suggest using const for variables that are never reassigned after declared.

    • Popular Use: "prefer-const": "error" to encourage the use of const over let where possible, which can make code clearer and reduce potential bugs.

  13. array-callback-return (Enforce Return in Array Method Callbacks):

    • Description: Enforces return statements in callbacks of array’s methods like .map(), .forEach(), .filter(), etc.

    • Popular Use: "array-callback-return": "warn" to ensure that these callbacks explicitly return values when expected.

  14. no-multiple-empty-lines (No Multiple Empty Lines):

    • Description: Disallows multiple empty lines.

    • Popular Use: "no-multiple-empty-lines": ["error", { "max": 1 }] to keep the code clean and readable.

  15. eol-last (End of Line Requirement for Files):

    • Description: Enforces that files end with a newline.

    • Popular Use: "eol-last": ["error", "always"] to ensure files end with a line break, which can improve compatibility with various tools and systems.

d

Last updated