Skip to content

TypeScript error when require eslint-plugin-jsdoc in a CommonJS file #1223

Open
@shadowspawn

Description

@shadowspawn

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. 😄

Quoting from FalseESM:

A golden rule of declaration files is that if they represent a module—that is, if they use import or export 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

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions