@krakentech/eslint-config v1.0.0
This package provides a wide range of "recommended" ESLint configs with the goal of minimising end-user configuration and increasing consistency across projects. It is designed around ESLint v9 to allow for easily shareable, modular and extensible configurations by leveraging the new "Flat" config files.
Installation
We publish our ESLint config publicy on npm
. No registry token or
authentication is required to install the config. Install it alongside the latest eslint version using your preferred
package manager:
pnpm add -D @krakentech/eslint-config eslint
yarn add -D @krakentech/eslint-config eslint
npm install --save-dev @krakentech/eslint-config eslint
!NOTE If you are using a monorepo it's still recommended to install the package at the root of the project. ESlint v9 is now able to apply rules top down, making it trivial to limit specific rule-sets to the right files. For example, the recommended NextJS package can easily be restricted to
apps/web
if that is the only NextJS application in the monorepo.
Configuration
ESLint v9 now enforces the use of a file named eslint.config.js
. This should be placed at the root of your project. Configuration of the whole repository can be done from this single file. Simply load the package and export linters.load(FlatConfig, ...)
.
Each FlatConfig
only requires the user to define which files
should have which plugins applied to them (or ignores
) and which plugins the config extends
from. You can pass as many configs as you like.
!IMPORTANT If you don't define any
files
for a config, the default behaviour it to lint all project files! This may affect performance.
// eslint.config.js
const linters = require("@krakentech/eslint-config");
module.exports = linters.load(
// Ignore all node_modules and dist folders
{
ignores: ["**/node_modules/**", "**/dist/**"],
},
// Apply recommended typescript rules to all
// Typescript files in the repo
{
files: ["**/*.{ts,tsx,mts,cts}"],
extends: linters.configs.typescript.recommended,
},
);
// eslint.config.js
const linters = require("@krakentech/eslint-config");
module.exports = linters.load(
// Also ignore next build folder
{
ignores: [
"**/node_modules/**",
"**/dist/**",
"**/.next/**"
],
},
// Apply recommended next rules to all apps
{
files: ["apps/**/*.{ts,tsx}"],
extends: linters.configs.next.recommended,
},
// Only apply typescript rules to packages
{
files: ["packages/**/*.{ts,mts,cts}"],
extends: linters.configs.typescript.recommended,
},
);
!TIP We support both CJS and ESM config files! You can use
import
andexport default
if your package package type is set tomodule
.
Fine tuning configurations
Whilst we suggest that you try to use the recommended
configurations where possible to maintain consistency across projects, it is still simple to "extend" our recommended configs and "override" specific rules.
Simple Typescript Package
For example, lets say we want to create a ReactJS project that uses Typescript and disables the @typescript-eslint/no-explicit-any
rule:
// eslint.config.js
const linters = require("@krakentech/eslint-config");
module.exports = linters.load(
// ... other configs
{
files: ["**/*.{ts,tsx}"],
extends: [
// Load recommended Javascript rules
...linters.configs.javascript.recommended,
// Load the recommended typescript configs
...linters.configs.typescript.recommended,
// Then extend it with the React config
...linters.configs.react.recommended,
],
// Override a specific rule
rules: {
"@typescript-eslint/no-explicit-any": "off",
},
},
);
Monorepo with multiple apps, packages and tests
// eslint.config.js
const linters = require("@krakentech/eslint-config");
module.exports = linters.load(
// Global ignores across the whole repo
{
ignores: ["**/node_modules/**", "**/build/**", "**/*.typegen.*/**"],
},
// Apply Javascript recommended rules to all js(x) and ts(x) files
{
files: ["**/*.{js,jsx,ts,tsx}"],
extends: linters.configs.javascript.recommended,
},
// Apply next recommended rules to all apps
{
files: ["apps/**/*.{ts,tsx}"],
extends: linters.configs.next.recommended,
},
// Only apply typescript rules to packages
{
files: ["packages/**/*.{ts,mts,cts}"],
extends: linters.configs.typescript.recommended,
},
// Applies react rules to all react files. This should also catch most test
// files too.
{
files: ["**/*.{jsx,tsx}"],
extends: [
...linters.configs.react.recommended, // Includes jsxa11y
],
},
// Applies jest rules to test files
{
files: ["**/*.spec.{js,jsx,ts,tsx}"],
extends: linters.configs.jest.recommended,
},
);
!TIP Some plugins have "utility" configs that do something specific to that plugin (usually to disable rules). Use these the same way you would use the
base
configs.
export type LinterConfig = {
base: FlatConfig;
recommended: ConfigArray;
utils?: Record<string, FlatConfig>;
};
export type PackageConfig = {
load: (...configs: InfiniteDepthConfigWithExtends[]) => ConfigArray;
configs: Record<string, LinterConfig>;
};
Plugins
The following plugins are supported by this package. Many of the recommended ConfigArray
's only contain the base plugin, however, the recommended Typescript, React and NextJS configs contain multiple plugins, for which the table below also indicates the other plugins that are loaded.
Plugin | Typescript | React | NextJS |
---|---|---|---|
@eslint/js | ✅ | ⛔ | ✅ |
typescript-eslint | ✅ | ⛔ | ✅ |
eslint-plugin-import | ✅ | ⛔ | ✅ |
eslint-plugin-simple-import-sort | ✅ | ⛔ | ✅ |
eslint-plugin-react | ⛔ | ✅ | ✅ |
eslint-plugin-react-hooks | ⛔ | ✅ | ✅ |
eslint-plugin-jsx-a11y | ⛔ | ✅ | ✅ |
@next/eslint-plugin-next | ⛔ | ⛔ | ✅ |
eslint-plugin-turbo | ⛔ | ⛔ | ⛔ |
@vitest/eslint-plugin | ⛔ | ⛔ | ⛔ |
eslint-plugin-jest | ⛔ | ⛔ | ⛔ |
eslint-plugin-prettier | ⛔ | ⛔ | ⛔ |
!IMPORTANT The recommended configs are configurations we think you should use in your projects, not that they necessarily use the recommended rules sets. Whilst most do use the recommended rule sets, it's good to check which rules sets using the JSDoc strings on each export or the plugin details below.
Examples
Base Configs
@eslint/js
Overrides
no-console
-["error", { allow: ["warn"] }]
typescript-eslint
We use the "Strict TypeChecked" rules (which automatically brings in the "Recommended" rules) to provide the most accurate type checking.
Overrides
@typescript-eslint/no-unused-vars
- Allows the use of the
_
prefix for unused variables - Will ignore unused destructured rest siblings:
{ ignoreMe, ...butNotMe } = someObject
- Allows the use of the
@typescript-eslint/consistent-type-imports
- Prefers types are always imported using the
type
keyword - e.g.
import { type Foo }
overimport { Foo }
- This works well the fixable rule
import/consistent-type-specifier-style
to ensure import consistency.
The following have been disabled:
@typescript-eslint/no-confusing-void-expression
- Off@typescript-eslint/restrict-template-expressions
- Off@typescript-eslint/no-unsafe-enum-comparison
- Off@typescript-eslint/unbound-method
- Off@typescript-eslint/no-floating-promises
- Off
!TIP We provide the
configs.typescript.utils.disableTypeChecking
utility to disable the type checking rules if you need to disable type checking for whatever reason (e.g. old JSX only components).
eslint-plugin-import
and eslint-plugin-simple-import-sort
We use both packages in configs.imports.recommended
. We prefer eslint-plugin-simple-import-sort
for import sorting because it requires less configuration to apply sensible sorting, is easier to configure and only creates an single issue if there's an error in the sorting. We also include eslint-plugin-import
for a few rules that the former does not handle:
import/first
- Ensure all imports appear before other statements.import/newline-after-import
- Enforce a newline after import statements.import/no-duplicates
- Forbid repeated import of the same module in multiple places.import/consistent-type-specifier-style
- Ensure that we consistently useimport { type Foo }
.
We provide the ability to disable the simple-import-sort
plugin if it does not fit well with your project. Simply extend your config with this utility like so:
// eslint.config.js
import linters from "@krakentech/eslint-config";
export default linters.load({
files: ["**/*.{ts,tsx}"],
extends: [
...linters.configs.typescript.recommended,
linters.configs.imports.utils.disableSimpleImportSort,
],
});
eslint-plugin-react
, eslint-plugin-react-hooks
and eslint-plugin-jsx-a11y
eslint-plugin-react
Recommended Rule Seteslint-plugin-jsx-a11y
Strict Rule Setreact-hooks/rules-of-hooks
- Enforce rules of hooks.react-hooks/exhaustive-deps
- Validate hook dependency arrays.
Overrides
react/prop-types
- Off.react/react-in-jsx-scope
- Off.
@next/eslint-plugin-next
eslint-plugin-turbo
@vitest/eslint-plugin
eslint-plugin-jest
eslint-plugin-prettier
!IMPORTANT Prettier is not enabled by default in our recommended configs. The official advice by both the Prettier team and the ESLint team is to not integrate Prettier rules into your ESLint config. Formatters should be something you forget about; lots of red squiggly lines in your editor can be distracting as well as less performant.
However, it is expected that users implement Prettier into their workflow at some point. Ideally users integrate Prettier into their editors, or you run Prettier as a file watcher.
Alternatively (or in addition to), you can conditionally enable Prettier during CI to ensure committed code is formatted correctly:
// eslint.config.js
// This is the common CI ennvar, however, adjust to your system
const isCI = process.env.CI;
export default linters.load(
...
// Enable Prettier in CI only
isCI && {
// No files array will lint all files
extends: linters.configs.recommended.prettier,
},
...
};
!NOTE Prettier should be enabled as your last config so that it can override any rules it might conflict with.
Rule Comparison
This table details which rules have been added or removed from the last major release (also compatibility with Biome given it looks like a promising upgrade from ESLint).
9 months ago
8 months ago
8 months ago
9 months ago
9 months ago
9 months 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
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago