Skip to content

Conversation

@mdmower-csnw
Copy link

@mdmower-csnw mdmower-csnw commented Oct 27, 2025

Summary

  • Use TS satisfies operator to ensure plugin adheres to the ESLint.Plugin shape while retaining its actual shape for export.
  • Assign configs as part of plugin assignment, only delaying the assignment of the plugin property in flat configs. This improves exported types without hacky assertions.
  • BREAKING CHANGE: flatten configs to match the expected shape:
    • Flat configs are now the default:
      • configs.recommended
      • configs['recommended-latest']
    • Legacy configs are now suffixed:
      • configs['recommended-legacy']
      • configs['recommended-latest-legacy']

- Use TS `satisfies` operator to ensure `plugin` adheres to the
  ESLint.Plugin shape while retaining its actual shape for export.
- Assign configs as part of `plugin` assignment, only delaying the
  assignment of the `plugin` property in flat configs. This improves
  exported types without hacky assertions.
- BREAKING CHANGE: flatten `configs` to match the expected shape:
  - Flat configs are now the default:
    - `configs.recommended`
    - `configs['recommended-latest']`
  - Legacy configs are now prefixed:
    - `configs['legacy-recommended']`
    - `configs['legacy-recommended-latest']`
@JstnMcBrd
Copy link

Un-nesting the flat configs is a good change 👍 It aligns with the consensus we reached back in October 2024.

For context, see this comment from the maintainer of eslint (and the surrounding conversation): #30774 (comment)

@mdmower-csnw mdmower-csnw marked this pull request as ready for review October 27, 2025 23:35
@kachkaev
Copy link
Contributor

kachkaev commented Oct 27, 2025

Should legacy be prefixed or suffixed? #30774 (comment) and official ESLint docs suggest it's the latter. Looking at Next.js, they've got plugin:@next/next/recommended-legacy (rather than plugin:@next/next/legacy-recommended).

- Switch to legacy suffix instead of prefix
@mdmower-csnw
Copy link
Author

Should legacy be prefixed or suffixed?

I'm impartial. I wasn't actually aware of any of these conversations when I posted this. I went ahead and changed to suffix.

@karlhorky
Copy link
Contributor

karlhorky commented Oct 28, 2025

cc @michaelfaith @poteto this PR is a revisiting of the config shape changes discussed with @nzakas in #30774:

@michaelfaith
Copy link
Contributor

Should legacy be prefixed or suffixed? #30774 (comment) and official ESLint docs suggest it's the latter. Looking at Next.js, they've got plugin:@next/next/recommended-legacy (rather than plugin:@next/next/legacy-recommended).

I agree. legacy- as a prefix is a bit more conventional.

All-in-all, a big fan of this change. The only thing that might be slightly confusing from a user's perspective is recommended-latest-legacy (or legacy-recommended-latest), since it's slightly self-contradictory.

rules: recommendedRuleConfigs,
},
'recommended-latest': {
plugins: {'react-hooks': {}},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I might suggest using a get accessor here, rather than assigning to an empty object and then re-assigning later. This is what we're doing in several of the plugins I work on:

e.g.
https://github.com/eslint-community/eslint-plugin-eslint-plugin/blob/main/lib/index.ts#L71-L75

recommended: {
  plugins: {
    get 'react-hooks'(): ESLint.Plugin {
      return plugin;
    }
  },
  rules: recommendedRuleConfigs,
},

Not a huge difference in the end, but keeps it self-contained.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would like to avoid using ESLint.Plugin directly in the exported type, relying on it only for the satisfies check. Using a getter as proposed requires this type assignment, though; it could not be inferred. {} satisfies the type for initial assignment (which is then replaced) and I don't see this negatively affecting users in a practical sense.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants