Skip to content

Change Request: Flat config extends #19116

@nzakas

Description

@nzakas

ESLint version

HEAD

What problem do you want to solve?

Now that more folks are moving to ESLint v9 and flat config, a common complaint is that it's difficult to extend configs from plugins. Whereas eslintrc had extends, flat config forces folks to insert objects into the export array, sometimes using the spread (...) syntax and sometimes not. It seems that this is a point of both confusion and frustration for some:

  1. For beginners, the spread syntax is confusing. I've spent time helping folks on Discord only to discover that they just didn't understand how to use the spread operator or what it does.
  2. For everyone, some plugins export config objects while others export config arrays, and so you never know whether or not to use the spread operator. [1] [2] [3]
  3. Further adding to the confusion, if you want to extend another config only for certain files, you need to write a bit of JavaScript for that too. This is also hostile for beginners and annoying for others.

I think overall, what we gained in flexibility has also resulted in an increase in complexity for setting up and editing config files. I think there's enough data showing that this is a problem and needs addressing.

What do you think is the correct solution?

I think we can address these problems with a couple of changes.

1. Allow nested arrays

First, we can allow arrays to be inserted directly into a flat config array and then flatten the config array. This would negate the need to use the spread syntax at all. This was part of the original RFC and later suggested to be enabled by @bradzacher. This is actually already implemented in @eslint/config-array as an option that is easy to toggle on. (We had kept it off to this point in the name of simplicity, but it seems like it would actually improve things to enable it.)

2. Introduce an extends key

We can normalize the experience of extending configs by reintroducing the extends key for flat configs. In flat configs, extends will not trigger any file loading. Instead, it will allow string identifiers for configs contained in plugins as well as objects. Here's a simple example:

import js from "@eslint/js";

export default [
    {
        plugins: {
            js
        },
        files: ["**/*.js"],
        extends: ["js/recommended"],
        rules: {
            "prefer-const": "off"
        }
    }
];

Here, we would see "js/recommended", which means "go to the js plugin and use the config named 'recommended'." We would then produce this equivalent config array during the normalization phase:

import js from "@eslint/js";

export default [
    {
        ...js.configs.recommended,       
        files: ["**/*.js"]
    },
    {
        plugins: {
            js
        },
        files: ["**/*.js"],
        rules: {
            "prefer-const": "off"
        }
    }
];

(We can also allow objects in the extends array, for which no lookup is required.)

This would require an RFC to iron out the details, and I'd definitely like some feedback before starting that process.

Participation

  • I am willing to submit a pull request for this change.

Additional comments

No response

Metadata

Metadata

Assignees

Labels

coreRelates to ESLint's core APIs and featuresenhancementThis change enhances an existing feature of ESLint

Type

No type

Projects

Status

Complete

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions