Description
Expected behavior
Able to use TypeScript for type checking in a CommonJS file which imports eslint-plugin-jdocs
(using require
).
Actual behavior
TypeScript fails on the require line for eslint-plugin-jdocs
in a CommonJS file.
$ tsc -p tsconfig.js.json
eslint.config.js:6:23 - error TS1479: The current file is a CommonJS module whose imports will produce 'require' calls; however, the referenced file is an ECMAScript module and cannot be imported with 'require'. Consider writing a dynamic 'import("eslint-plugin-jsdoc")' call instead.
To convert this file to an ECMAScript module, change its file extension to '.mjs' or create a local package.json file with `{ "type": "module" }`.
6 const jsdoc = require('eslint-plugin-jsdoc');
My understanding of the problem is that TypeScript best practice is a definition file corresponds to a single JavaScript file. I am guessing when TypeScript finds the types
file for eslint-plugin-jdocs of ./dist/index.d.ts
, it assumes the corresponding JavaScript file will be the esm flavour since eslint-plugin-jdocs has "type": "module"
and the .d.ts
is therefore implicitly esm.
There is a project which champions technically correct TypeScript setups and picks up a potential problem. This might be more convincing than my scenario. 😄
- https://arethetypeswrong.github.io/?p=eslint-plugin-jsdoc%4048.2.3
- https://github.com/arethetypeswrong/arethetypeswrong.github.io/blob/main/docs/problems/FalseESM.md
Quoting from FalseESM:
A golden rule of declaration files is that if they represent a module—that is, if they use
import
orexport
at the top level—they must represent exactly one JavaScript file. They especially cannot represent JavaScript files of two different module formats.
I was able to fix my error without actually creating a separate definition file by modifying eslint-plugin-jdocs package.json
file like this, but I suspect it is not robust so more for interest than a suggestion!
"exports": {
"import": {
"types": "./dist/index.d.ts",
"default": "./src/index.js"
},
"require": {
"types": "./dist/index.d.ts",
"default": "./dist/index.cjs"
}
},
I assume the robust solution would be to have an explicit definition file for cjs (say): index.d.cts
.
TypeScript is normally fairly forgiving about this problem to avoid breaking consumers (microsoft/TypeScript#50762 (comment)) and I seem to have stumbled on a case where it notices.
Happy to work on a simple reproduction if you would like to see TypeScript failure yourself rather than just the arethetypeswrong
warning, and willing to work on a PR.
Environment
- Node version: v20.11.1
- ESLint version v8.56.0
eslint-plugin-jsdoc
version: 48.2.3- TypeScript version: 5.2.2