-
Notifications
You must be signed in to change notification settings - Fork 76
Description
Environment
Node version: v22.15.0
npm version: v11.3.0
Local ESLint version: v9.27.0 (Currently used)
Global ESLint version: Not found
Operating System: linux 5.15.167.4-microsoft-standard-WSL2
What parser are you using?
Default (Espree)
What did you do?
I have installed some plugins and configured ESLint to use them. ESLint works fine, but TypeScript throws some type errors related to exactOptionalPropertyTypes
, which I have set to true
in my tsconfig.json
since I'm extending from @tsconfig/strictest
.
What did you expect to happen?
There should be no type errors when using exactOptionalPropertyTypes
.
What actually happened?
Type errors occurred.
Link to Minimal Reproducible Example
https://stackblitz.com/edit/vitejs-vite-gantpukn?file=eslint.config.mjs,tsconfig.json&view=editor
Participation
- I am willing to submit a pull request for this issue.To pick up a draggable item, press the space bar. While dragging, use the arrow keys to move the item. Press space again to drop the item in its new position, or press escape to cancel.
Additional comments
I have 2 reproductions:
- https://stackblitz.com/edit/vitejs-vite-gantpukn?file=eslint.config.mjs,tsconfig.json&view=editor: Contains a minimal reproducible example. It reproduces the error using a single plugin
@eslint/markdown
. - https://stackblitz.com/edit/stackblitz-starters-rh2kntpu?file=eslint.config.mjs,tsconfig.config.json&view=editor: This is the configuration where I experienced the issue. It makes use of many plugins, so there are more type errors. You may notice that
eslint
does not work in this repro. This is because npm fails to installeslint-import-resolver-typescript
, which requires native modules. It works if you download the code and run it locally. You can also make it work by force installing@unrs/resolver-binding-wasm32-wasi
as suggested in Failed to load native bindings on linux x64 platform import-js/eslint-import-resolver-typescript#431. I did not do this because it breaksnpm i
and I did not want to break the repo.
According to @nzakas: "The Plugin
type exported from eslint is the thing that needs updating to address this." (#391 (comment))
Metadata
Metadata
Assignees
Labels
Type
Projects
Status
Activity
exactOptionalPropertyTypes
in type definitions #391sebastian-altamirano commentedon May 28, 2025
If
exactOptionalPropertyTypes
is set tofalse
at https://stackblitz.com/edit/stackblitz-starters-rh2kntpu?file=eslint.config.mjs,tsconfig.config.json&view=editor, there are still type errors.These are for a different issue, but I’m unsure whether they fall under ESLint’s responsibility, the plugins' responsibility, or if my configuration needs adjustments. Any thoughts on where this should be addressed so that I can create the corresponding issues?
fasttime commentedon May 28, 2025
Thanks for the issue @sebastian-altamirano. I can see that the
@eslint/markdown
types for theprocessor
config include some optional properties with valueundefined
, which are inconsistent with how configs in ESLit are typed.from https://app.unpkg.com/@eslint/markdown@6.4.0/files/dist/esm/index.d.ts#L184-213:
Note that
files
,processor
,languageOptions
,rules
,plugins
are explicitly typed with the valueundefined
in some of the config objects. To me, this looks like a tsc compiler artifact given that none of these properties are specified as undefined in the source code (https://github.com/eslint/markdown/blob/v6.4.0/src/index.js#L108-L134).fasttime commentedon May 28, 2025
I tried running
npm run check-eslint-config
in the above repro, and I'm getting the same error messages with or without theexactOptionalPropertyTypes
option set, so yes, these don't seem related to the behavior of that option in particular.If you encounter any incompatibilities with third party plugins it's better to file a bug at the plugin's maintainers, because ESLint doesn't provide the types for those plugins, and we can't support tools that we don't maintain.
Now, in the case of the
eslint.config.mjs
file in the StackBlitz repro, the compiler errors arise from the fact that some of the plugins in that config (angular-eslint
,eslint-plugin-import-x
,@smarttools/eslint-plugin-rxjs
,typescript-eslint
and possibly more) use type definitions provided by TSESlint, which are not compatible with native ESLint types. We had reports of similar incompatibilities in the past (e.g. eslint/eslint#19467). The inconsistencies are partly due to historical reasons, because typescript-eslint provided types for the flat config API before ESLint did.sebastian-altamirano commentedon May 28, 2025
Makes sense! Since
@eslint/markdown
does not add a type anotation for theplugin
constant, TypeScript does its best to infer one, resulting in that unusual type withundefined
values. Given this, I believe my original PR #391 makes more sense now.I did not know that! So that's why there are no errors when using
tseslint.config()
.fasttime commentedon Jun 2, 2025
Sorry for the delay! I think there isn't much we can do address the incompatibilities with third-party plugins because of the above reasons. As for the issue with the
eslint/markdown
types, it should be probably addressed in that repo. The problem is that we don't use theexactOptionalPropertyTypes
option to build the type declarations, and tsc creates types that are perfectly valid without that option. There are a few ways to fix this issue. Without adding excessive complexity to the build process, I can think of at least three solutions:Type config explicitly
This approach would consist in coercing the type of the
recommended-legacy
config toLegacyConfig
, and the type of theprocessor
andrecommended
configs toConfig[]
. This can be achieved with a@type
tag annotation as you did in #391 e.g.:The resulting type will be:
This seems safe as the elements of individual config objects are not typically accessed directly.
Use a helper function
Another option is using a helper function to type the
processor
config as a tuple rather than as an array, as suggested in microsoft/TypeScript#27179 (comment):The generated types will look like:
This is more correct than manual typing with
Config[]
, but adds a function call.Build type declarations with
exactOptionalPropertyTypes
The
exactOptionalPropertyTypes
option requiresstrictNullChecks
, which we don't use, because it would generate errors. The errors can be disabled withnoCheck
, but that would also turn off errors that we don't want to miss upon. This means that in order to fail the build with an error if the types aren't correct, we'll have to run tsc another time withoutnoCheck
but withnoEmit
, so that no types are generated. The whole command line would be like this:And the generated type for the
processor
config:Note that
undefined
is now replaced bynever
. This is the most robust solution as it would avoid future incompatibilities that could arise because ofexactOptionalPropertyTypes
in that plugin.31 remaining items
eslint-github-bot commentedon Sep 14, 2025
👋 Hi! This issue is being addressed in pull request #524. Thanks, @lumirlumir!
eslint-github-bot commentedon Sep 14, 2025
👋 Hi! This issue is being addressed in pull request #524. Thanks, @lumirlumir!
lumirlumir commentedon Sep 14, 2025
It took quite a while to find the right solution for this, but I was able to figure it out and have opened a PR with the fix.
If it's alright, I am assigning myself to this issue since it's been some time since we last discussed solutions for it.
eslint-github-bot commentedon Sep 15, 2025
👋 Hi! This issue is being addressed in pull request #524. Thanks, @lumirlumir!
eslint-github-bot commentedon Sep 15, 2025
👋 Hi! This issue is being addressed in pull request #524. Thanks, @lumirlumir!
eslint-github-bot commentedon Sep 15, 2025
👋 Hi! This issue is being addressed in pull request #524. Thanks, @lumirlumir!
eslint-github-bot commentedon Sep 15, 2025
👋 Hi! This issue is being addressed in pull request #524. Thanks, @lumirlumir!
exactOptionalPropertyTypes
option to type test css#259exactOptionalPropertyTypes
option to type test json#144exactOptionalPropertyTypes
option to type test rewrite#270