Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Import broken for CJS-targeted TypeScript projects #5711

Open
3 of 10 tasks
rflechtner opened this issue Aug 24, 2023 · 0 comments
Open
3 of 10 tasks

Import broken for CJS-targeted TypeScript projects #5711

rflechtner opened this issue Aug 24, 2023 · 0 comments

Comments

@rflechtner
Copy link
Contributor

rflechtner commented Aug 24, 2023

EDIT: updated the reproduction example to reflect the proper use of typescript's Node16 module setting.

  • I'm submitting a ...

    • Bug report
    • Feature request
    • Support request
    • Other
  • What is the current behavior and expected behavior?

The following setup currently results in a 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'. error thrown by TypeScript:

index.ts

import * as api from '@polkadot/api'

tsconfig.json

{
  "compilerOptions": {
    "target": "ESNext",             
    "module": "NodeNext", // using Node16 or setting "moduleResolution": "Node16" results in the same behaviour
  }
}        

package.json
"type" is set to "commonjs" or omitted, both of which result in code being emitted for the commonjs module system (alternatively, the error can be provoked by renaming index.ts to index.cts, which has the same effect)

The reason for that is likely that typings are only provided in the root of the project, which, due to the top-level type field is interpreted as ESM, as when using Node16/NodeNext module settings TS follows node's logic for inferring module type. The type export strategy may need to be adjusted to allow properly importing from a TS project that builds to CJS.

  • What is the motivation for changing the behavior?

I'm still struggling myself to figure out how to use the conditional exports map correctly to make TS aware of both a CJS and ESM implementation being present in a package, but from first experiments with strategies mentioned in this issue I can report that the following strategies seem to fix this:

  1. Move .d.ts files to cjs folder instead
    Because the CJS folder contains a package.json with "type": "commonjs", the typings are now interpreted as CJS.
    While TS takes issue with with CJS trying to import ESM, the converse is not the case. Not sure we'd provoke other unexpected issues with that though, so better:

  2. Provide separate typings for CJS code
    Build CJS code with declarations, living in the CJS folder. You'd obviously have to modify the exports map as well, the following strategies seem to work:

  • 2a) Remove "types" entry from exports map entirely. As long as there is a *.d.ts file accompanying every *.js export Typescript seems to be picking them automatically.
  • 2b) Point to the right declaration file for each import strategy, e.g.
      ".": {
        "import": {
          "types": "./index.d.ts",
          "default": "./index.js"
        },
        "require": {
          "types": "./cjs/index.d.ts",
          "default":  "./cjs/index.js"
        }
      },
    
  • Please tell us about your environment:
  • Version: 10.9.1

  • Environment:

    • Node.js
    • Browser
    • Other (limited support for other environments)
  • Language:

    • JavaScript
    • TypeScript (include tsc --version) -> Version 5.1.6
    • Other
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Development

No branches or pull requests

1 participant