ESLint 10 🛡️ The @eslint/js Package — Importing recommended configs
The @eslint/js package is the source of ESLint’s core recommended rule set. It is a separate npm package from eslint itself, and it exports a single object: configs.recommended. That object contains the severity settings for the rules that the ESLint team considers the baseline for every JavaScript project. Importing it into the flat config array is the standard first step in almost every configuration, and it is the replacement for the legacy "extends": "eslint:recommended" string that the old .eslintrc format used.
This chapter covers the package itself, the shape of the recommended object, the import pattern in the flat config array, the defineConfig and extends alternative, and the scoping rule that prevents the recommended config from applying to files it was not meant for.
Key point: js.configs.recommended is an object, not an array. It can be placed directly in the config array, or spread into an object that has a files key to scope it. The defineConfig helper accepts it inside an extends array, which is the cleaner syntax for projects that use the helper.
Why the package is separate from ESLint
The decoupling problem. The core eslint package contains the linter, the CLI, and the rule implementations. The recommended rule set is a configuration decision, not a linter implementation detail. Separating it into @eslint/js allows the recommended set to evolve on its own release cadence and allows projects to depend on the config without depending on a specific ESLint version’s internal structure.
The import problem. In the legacy format, the recommended set was enabled with a string: "extends": "eslint:recommended". The flat config removed the string-based extends for core configs. The @eslint/js package is the explicit replacement: install it, import it, and place the object in the array . The TypeScript-ESLint getting-started guide lists @eslint/js alongside eslint and typescript-eslint as the packages to install for a standard setup .
The scoping problem. The js.configs.recommended object has no files key. When it is placed directly in the array, it applies to every file that ESLint processes. This is the intended behavior for a base config. But when a project has TypeScript files, the core no-unused-vars rule can produce false positives on type-only imports, and the TypeScript-aware replacement from typescript-eslint is needed. The recommended config is still the base; the TypeScript config layers on top of it.
a. The recommended object
The object exported by @eslint/js has a single rules key. The keys of that object are the rule IDs, and the values are the severities. The rules are a curated subset of the full rule list, chosen because they catch likely bugs or enforce universally agreed-upon correctness.
// The shape of js.configs.recommended (simplified)
{
rules: {
'no-undef': 'error',
'no-unused-vars': 'error',
'no-redeclare': 'error',
// ... other core rules
}
}
The exact set changes between major ESLint versions. A rule that is error in one version may be removed or downgraded in the next. This is why the package is versioned separately from eslint: a project can upgrade ESLint without necessarily changing the recommended rule set, and vice versa.
b. The direct import pattern
The most common pattern is to import the package and place the object in the array.
// eslint.config.js
import js from '@eslint/js'
export default [
js.configs.recommended,
{
rules: {
'no-console': 'warn',
},
},
]
The js.configs.recommended object applies to every file. The second object adds a project-specific rule on top. Because the second object is later in the array, its no-console setting takes precedence for any file it matches.
When the recommended config should apply only to a subset of files, it can be spread into an object with a files key.
import js from '@eslint/js'
export default [
{
files: ['**/*.js', '**/*.mjs', '**/*.cjs'],
...js.configs.recommended,
},
]
This pattern scopes the recommended rules to JavaScript files only. A TypeScript file in the same project would not receive them, which is the correct behavior when the TypeScript config provides its own equivalent rules.
c. The defineConfig and extends pattern
The defineConfig helper, introduced in ESLint 9.22, provides an extends key that accepts config objects and arrays. The TypeScript-ESLint getting-started guide uses this pattern as the recommended setup.
// eslint.config.mjs
import js from '@eslint/js'
import { defineConfig } from 'eslint/config'
export default defineConfig([
{
files: ['**/*.js', '**/*.mjs'],
extends: [js.configs.recommended],
rules: {
'no-console': 'warn',
},
},
])
The extends array is flattened by defineConfig, so the js.configs.recommended object is applied to the files matched by the outer files key. This is cleaner than the spread pattern because the scoping and the extension are expressed separately, and the defineConfig wrapper provides type safety in TypeScript .
The @eslint/js package is also used in the legacy-style setup that some tutorials still show, where the recommended config is spread into an object with ignores and other options. The pattern from a Stack Overflow revision spreads eslint.configs.recommended into an object that also sets ignores, which scopes the recommended rules while excluding specific files .
Complete Example Session
// ============================================
// PART 1: THE PACKAGE INSTALLATION
// ============================================
// npm install --save-dev eslint @eslint/js
//
// The @eslint/js package is separate from eslint.
// ============================================
// PART 2: THE DIRECT IMPORT
// ============================================
import js from '@eslint/js'
export default [
js.configs.recommended,
]
// The recommended rules apply to every file.
// ============================================
// PART 3: ADDING PROJECT RULES
// ============================================
import js from '@eslint/js'
export default [
js.configs.recommended,
{
rules: {
'no-console': 'warn',
'eqeqeq': 'error',
},
},
]
// The project rules override or extend the recommended set.
// ============================================
// PART 4: SCOPING THE RECOMMENDED CONFIG
// ============================================
import js from '@eslint/js'
export default [
{
files: ['**/*.js', '**/*.mjs', '**/*.cjs'],
...js.configs.recommended,
},
]
// The recommended rules apply only to JS files.
// ============================================
// PART 5: THE defineConfig PATTERN
// ============================================
import js from '@eslint/js'
import { defineConfig } from 'eslint/config'
export default defineConfig([
{
files: ['**/*.js'],
extends: [js.configs.recommended],
},
])
// defineConfig flattens the extends array.
// ============================================
// PART 6: THE TYPESCRIPT COMBINATION
// ============================================
import js from '@eslint/js'
import tseslint from 'typescript-eslint'
export default [
js.configs.recommended,
...tseslint.configs.recommended,
]
// The core rules plus the TypeScript rules.
// ============================================
// PART 7: THE SCOPED TYPESCRIPT COMBINATION
// ============================================
import js from '@eslint/js'
import tseslint from 'typescript-eslint'
export default [
js.configs.recommended,
{
files: ['**/*.ts', '**/*.tsx'],
extends: [tseslint.configs.recommended],
},
]
// The TypeScript rules are scoped to TS files.
// ============================================
// PART 8: THE PRETTIER COMBINATION
// ============================================
import js from '@eslint/js'
import eslintConfigPrettier from 'eslint-config-prettier'
export default [
js.configs.recommended,
eslintConfigPrettier,
]
// Prettier config turns off formatting rules.
// It must be last.
// ============================================
// PART 9: THE COMPLETE CONFIG
// ============================================
import js from '@eslint/js'
import tseslint from 'typescript-eslint'
import eslintConfigPrettier from 'eslint-config-prettier'
export default [
{ ignores: ['dist/'] },
js.configs.recommended,
...tseslint.configs.recommended,
eslintConfigPrettier,
]
// ============================================
// PART 10: THE LEGACY EQUIVALENT
// ============================================
// Legacy .eslintrc:
// { "extends": "eslint:recommended" }
//
// Flat config:
// import js from '@eslint/js'
// js.configs.recommended
The ten parts covered the installation, the direct import, adding project rules, scoping the recommended config, the defineConfig pattern, the TypeScript combination, the scoped TypeScript combination, the Prettier combination, the complete config, and the legacy equivalent.
Quick Reference
The package
| Item | Value |
|---|---|
| Package name | @eslint/js |
| Install command | npm install --save-dev @eslint/js |
| Default export | js.configs.recommended |
| Object shape | { rules: { ... } } |
| Scope | All files unless scoped with files |
Import patterns
| Pattern | Syntax | Scoping |
|---|---|---|
| Direct | js.configs.recommended | All files |
| Spread | { files: [...], ...js.configs.recommended } | Matching files |
| Extends | extends: [js.configs.recommended] | Outer files |
Common combinations
| Combination | Order |
|---|---|
| Recommended + project rules | Recommended first |
| Recommended + TypeScript | Recommended first |
| Recommended + Prettier | Prettier last |
| Recommended + ignores | Ignores first |
The legacy equivalent
| Legacy | Flat config |
|---|---|
"extends": "eslint:recommended" | import js from '@eslint/js' + js.configs.recommended |
Best Practices
✅ Do This:
// Place the recommended config first
export default [js.configs.recommended, { rules: { ... } }] // ✅
// Scope the recommended config to JavaScript files
{ files: ['**/*.js'], ...js.configs.recommended } // ✅
// Use defineConfig for the extends pattern
defineConfig([{ files: ['**/*.js'], extends: [js.configs.recommended] }]) // ✅
// Put eslint-config-prettier last
export default [js.configs.recommended, eslintConfigPrettier] // ✅
❌ Don’t Do This:
// Use the legacy extends string
"extends": "eslint:recommended" // ❌
// Assume the recommended config includes TypeScript rules
js.configs.recommended // no TS rules // ❌
// Put Prettier before the recommended config
export default [eslintConfigPrettier, js.configs.recommended] // ❌
Common Pitfalls
| Pitfall | Why It Happens | Fix |
|---|---|---|
@eslint/js not found | Package not installed | npm install --save-dev @eslint/js |
| Recommended rules fire on TS files | Config not scoped | Spread into an object with files |
| Prettier and ESLint conflict | Prettier config not last | Put eslint-config-prettier at the end |
Legacy extends string fails | Flat config does not support it | Import js.configs.recommended |
| Rules missing after upgrade | Recommended set changed | Check the ESLint release notes |
Real-World Examples
1. Direct import
import js from '@eslint/js'
export default [js.configs.recommended]
2. With project rules
export default [js.configs.recommended, { rules: { 'no-console': 'warn' } }]
3. Scoped
{ files: ['**/*.js'], ...js.configs.recommended }
4. defineConfig extends
defineConfig([{ files: ['**/*.js'], extends: [js.configs.recommended] }])
5. With TypeScript
export default [js.configs.recommended, ...tseslint.configs.recommended]
6. With Prettier
export default [js.configs.recommended, eslintConfigPrettier]
7. The install command
npm install --save-dev eslint @eslint/js
8. The legacy equivalent
"extends": "eslint:recommended"
9. The object shape
{ rules: { 'no-undef': 'error' } }
10. The complete config
import js from '@eslint/js'
export default [{ ignores: ['dist/'] }, js.configs.recommended]
Visual
The package relationship
┌─────────────────────────────────────────────────────────────┐
│ eslint (the linter) │
│ └── @eslint/js (the recommended config) │
│ └── configs.recommended │
│ └── { rules: { ... } } │
└─────────────────────────────────────────────────────────────┘
The import flow
┌─────────────────────────────────────────────────────────────┐
│ import js from '@eslint/js' │
│ │ │
│ ▼ │
│ js.configs.recommended │
│ │ │
│ ▼ │
│ Placed in the config array │
│ │ │
│ ▼ │
│ Applied to files (all or scoped) │
└─────────────────────────────────────────────────────────────┘
The array order
┌─────────────────────────────────────────────────────────────┐
│ [ │
│ { ignores: ['dist/'] }, ← global ignore │
│ js.configs.recommended, ← base rules │
│ ...tseslint.configs.recommended, ← TypeScript rules │
│ eslintConfigPrettier, ← disable formatting │
│ { rules: { 'no-console': 'warn' } } ← project rules │
│ ] │
└─────────────────────────────────────────────────────────────┘
The legacy migration
┌─────────────────────────────────────────────────────────────┐
│ Legacy Flat config │
│ │
│ { "extends": "eslint:recommended" } │
│ │ │
│ ▼ │
│ import js from '@eslint/js' │
│ export default [js.configs.recommended] │
└─────────────────────────────────────────────────────────────┘
Summary
| Item | Value |
|---|---|
| Package | @eslint/js |
| Import | import js from '@eslint/js' |
| Config object | js.configs.recommended |
| Shape | { rules: { ... } } |
| Placement | First in the array (base config) |
| Scoping | Spread into an object with files |
defineConfig pattern | extends: [js.configs.recommended] |
| Legacy equivalent | "extends": "eslint:recommended" |
| Prettier order | eslint-config-prettier last |
Key takeaways:
@eslint/jsis the explicit replacement for the legacyeslint:recommendedstring. The flat config removed the string-based core extends. The package exports the recommended rule set as an object that is placed in the config array .- The recommended object applies to all files unless scoped. It has no
fileskey of its own. When a project needs the recommended rules only for JavaScript files, the object is spread into an object with afilespattern. - The base config goes first in the array. The recommended config is the foundation. The TypeScript rules, the project-specific rules, and the Prettier disables are layered on top, and the later objects override the earlier ones for the files they match.
defineConfigprovides anextendskey for the cleaner pattern. The TypeScript-ESLint getting-started guide usesextends: [js.configs.recommended]inside adefineConfigcall, which scopes the recommended config to the outerfilespattern .- Prettier’s config must be last.
eslint-config-prettierdisables the formatting rules that conflict with Prettier. If it is placed before the recommended config, the recommended config re-enables the rules that Prettier just disabled. - The package is a separate dependency. Installing
eslintalone does not install@eslint/js. The install command for a standard setup includes both, along withtypescript-eslintfor TypeScript projects .
Remember: The @eslint/js package is the source of the core recommended rules in the flat config. Import it, place js.configs.recommended at the beginning of the array, and layer the project-specific and framework-specific configs on top. Scope it with files if it should not apply to every file. Use defineConfig and extends for the cleaner syntax. And put eslint-config-prettier last so the formatting rules stay disabled.
Stop using slow, ad-bloated tool sites! 🤮
🔎 Search “KandZ Tools” on Google to use many professional utilities for free.
KandZ.me is the ultimate minimalist hub for:
✅ Finance (Mortgage, Interest, Inflation)
✅ Tech (Base64, JSON, Dev Suite, IP)
✅ Health (BMI, BMR, TDEE)
✅ Productivity (Timer, Workspace, QR)
⚡️ Fast & Private
🔒 No data leaves your device
💎 100% Free
🔗 Use it now: https://tools.kandz.me
🔖 Bookmark it—you’ll need it later!