@krakentech/eslint-config
A publicly available ESLint config by Octopus Energy Group.
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.
Do I need a shared package in a monorepo?
-
Probably not! Because of how ESLint v9 and the new "Flat" configs work, this package is able to define all of the different plugins as dependencies. So, rather than having to create a shared eslint config we can easily just install this package at the root to share it across the whole repo.
-
If you would prefer to use a shared package or per-package config files then you can too. Install this package into the shared package and distribute accordingly. This package does not mind how you want to setup your repo.
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.
Single Package Example | Monorepo Example |
---|
const linters = require("@krakentech/eslint-config");
module.exports = linters.load(
{
ignores: ["**/node_modules/**", "**/dist/**"],
},
{
files: ["**/*.{ts,tsx,mts,cts}"],
extends: linters.configs.typescript.recommended,
},
);
|
const linters = require("@krakentech/eslint-config");
module.exports = linters.load(
{
ignores: [
"**/node_modules/**",
"**/dist/**",
"**/.next/**"
],
},
{
files: ["apps/**/*.{ts,tsx}"],
extends: linters.configs.next.recommended,
},
{
files: ["packages/**/*.{ts,mts,cts}"],
extends: linters.configs.typescript.recommended,
},
);
|
[!TIP]
We support both CJS and ESM config files! You can use import
and export default
if your package package type is set to module
.
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:
const linters = require("@krakentech/eslint-config");
module.exports = linters.load(
{
files: ["**/*.{ts,tsx}"],
extends: [
...linters.configs.javascript.recommended,
...linters.configs.typescript.recommended,
...linters.configs.react.recommended,
],
rules: {
"@typescript-eslint/no-explicit-any": "off",
},
},
);
Monorepo with multiple apps, packages and tests
const linters = require("@krakentech/eslint-config");
module.exports = linters.load(
{
ignores: ["**/node_modules/**", "**/build/**", "**/*.typegen.*/**"],
},
{
files: ["**/*.{js,jsx,ts,tsx}"],
extends: linters.configs.javascript.recommended,
},
{
files: ["apps/**/*.{ts,tsx}"],
extends: linters.configs.next.recommended,
},
{
files: ["packages/**/*.{ts,mts,cts}"],
extends: linters.configs.typescript.recommended,
},
{
files: ["**/*.{jsx,tsx}"],
extends: [
...linters.configs.react.recommended,
],
},
{
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.
Why do we use extends
The load
utility automatically merges configs inside of the extends
field into a single config. This means we don't have to do fiddly spreading of multiple base
configs.
Package Interface
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
Overrides
no-console
- ["error", { allow: ["warn"] }]
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
@typescript-eslint/consistent-type-imports
- Prefers types are always imported using the
type
keyword - e.g.
import { type Foo }
over import { 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).
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 use import { type Foo }
.
configs.imports.utils.disableSimpleImportSort
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:
import linters from "@krakentech/eslint-config";
export default linters.load({
files: ["**/*.{ts,tsx}"],
extends: [
...linters.configs.typescript.recommended,
linters.configs.imports.utils.disableSimpleImportSort,
],
});
Overrides
react/prop-types
- Off.react/react-in-jsx-scope
- Off.
[!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:
const isCI = process.env.CI;
export default linters.load(
...
isCI && {
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).
Dependabot
If Dependabot is configured on your project, it will create Pull Requests to update @krakentech/eslint-config
automatically when we update it, so you never need to worry about linting dependencies again.
Releasing updates
Following instructions for @changesets/cli;
Whenever you make a change, run pnpm changeset
to generate documentation and include this in your last commit.
When you're ready to release changes (not necessarily after each change), follow the documentation from the changesets package above.
You may need to create a .npmrc file in packages/eslint-config
containing the following. The authToken
can be found under "NPMJS - Global Write access token" in the KT - Vendors 1Password entry:
@krakentech:registry=https://registry.npmjs.org/
//registry.npmjs.org/:_authToken=WRITE_ACCESS_TOKEN_FROM_1PASSWORD
To use your new release,
- Make a tea or coffee first, as npm takes a few minutes to propagate
- Use
yarn add -D @krakentech/eslint-config@x.y.z
to install the new release
If you have trouble, check the package hasn't been made private inadvertently. Logging into our npm organisation account is required to fix this if broken.