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

Cannot import named export from a typescript file in a workspace package if entry is using es modules and other package is not. #38

Open
remorses opened this issue Jun 19, 2022 · 16 comments
Labels
bug Something isn't working interop

Comments

@remorses
Copy link

remorses commented Jun 19, 2022

Cannot import named export from a typescript file in a workspace package if entry is using es modules and other package is not.

tsx will throw

SyntaxError: The requested module 'ts-package/src/file' does not provide an export named 'x'

I know this could be considered a node limitation but maybe we can compile typescript files to esm if entry is esm (even if workspace package does not have "type": "module"

Repro: https://github.com/remorses/tsx-repros

pnpm i
pnpm run import-ts-file
@privatenumber privatenumber added the bug Something isn't working label Jun 20, 2022
privatenumber added a commit that referenced this issue Jun 21, 2022
@privatenumber
Copy link
Owner

privatenumber commented Jun 21, 2022

I investigated this and it might be tough to fix.

When a ESM file imports a CommonJS file, you would imagine a loader could simply transform the CommonJS file to ESM syntax on import so it's interoperable.

However, Node.js actually bypasses the CJS loader and reads the CommonJS file directly from disk to statically detect named exports with cjs-module-lexer.

Static analysis is likely necessary because the import statement must assert that the named export exists before running the file. And even if Node.js adds a hook to transform the file before statically analyzing it, we won't be able to support older Node.js versions.

I tackled this problem before (evanw/esbuild#2248) but arrived at the same conclusion. However, I managed to fix it for dynamic imports.

@loynoir

This comment was marked as off-topic.

@loynoir

This comment was marked as off-topic.

@privatenumber

This comment was marked as off-topic.

@loynoir

This comment was marked as off-topic.

@loynoir

This comment was marked as off-topic.

@privatenumber

This comment was marked as off-topic.

@loynoir

This comment was marked as off-topic.

@privatenumber
Copy link
Owner

Sorry, I don't understand what you're saying. I'm going to hide your comments because they're cryptic and makes this thread harder to follow.

In the future, please provide a reproduction when you report a problem. That would be the best way to communicate it, especially if it's not easy to describe it.

@kubijo
Copy link

kubijo commented Feb 5, 2023

I have just crashed against what seems like the same problem that @loynoir was trying to explain...

Essentially, there doesn't seem to be a way to import ts / js + d.ts modules from an mts entry point module.

My situation is that I have a non-module workspace in which I'm creating a typescript server module. This has to have an mts extension to convince typescript that it doesn't share a single huge scope with everything around.

The modules that I am trying to import are generated from proto-gen-es and the most correct & compatible version of generated artefacts is the aforementioned js + d.ts option, with imports explicitly including .js.

That however doesn't work with tsx since it keeps replacing the .js imports extension to .ts.
What does work is renaming everything to mts and importing with mjs

To illustrate, here is what I observed

/**
 * - "a.js" & "a.d.ts" exist
 * - results in "tsx" trying to import "a.ts"
 */
import {a} from `../gen/a.js`;

/**
 * - same files as before
 * - tries and fails to import verbatin (extentionless)
 */
import {a} from `../gen/a`;

/**
 * - "a.ts" exists
 * - produces following error, probably meaning it does't consider it a module:
 *     index.mts:1
 *     import {a} from 'a.js';
 *             ^
 *     SyntaxError: The requested module 'a.js' does not provide an export named 'a'
 */
import {a} from '../gen/net_pb.js';

Considering that these are my options of generated code, I'm seemingly left with an only option… generate the code with options target=ts,import_extension=.mjs and rename all files to mts

@kubijo
Copy link

kubijo commented Feb 5, 2023

I have also tried adding "type": "module" into package.json, renaming the entry module to ts and generating js+dts modules with js imports, but that also doesn't work producing errors in transitive imports where it replaces js extensions to ts and fails.

What does work is:

  • "type": "module" context
  • index.ts
  • ts files with js imports

With all that said, my context is Yarn V3 workspace with PNP enabled and node@19.6.0.
Yarn, however, doesn't seem to be the problem here, the algorithm for manipulation with extensions does.

It might also be worth mentioning that the type: module thing can yet prove problematic, since ES modules are still a bag of wet mice when it comes to interop between the plethora of modules for frontend development (storybook, yarn PnP, linters)

@privatenumber
Copy link
Owner

privatenumber commented Dec 5, 2023

Worth mentioning this bug prevents named imports from lodash: #361

Also, this is finally fixable when this lands in Node nodejs/node#50839

@raveclassic

This comment was marked as resolved.

junhoyeo added a commit to mint-cash/burndrop-contracts that referenced this issue Feb 19, 2024
maxpatiiuk added a commit to specify/specify7 that referenced this issue Feb 20, 2024
Workaround for privatenumber/tsx#38
But also, it's time for those to be TypeScript
Note, I added `// @ts-nocheck` to the top of the files to suppress
TypeScript errors for now, but this should be removed once we move way
from Backbone
@privatenumber
Copy link
Owner

Currently blocked by nodejs/node#51327

@thoroc

This comment has been minimized.

@privatenumber
Copy link
Owner

The issue is acknowledged, and the blocker is referenced above. Contributions to the Node project to fix the issue will be appreciated.

To maintain focus, I'm locking this thread until unblocked, but encourage constructive solution-oriented dialogue through PRs.

Repository owner locked and limited conversation to collaborators Feb 27, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
bug Something isn't working interop
Projects
None yet
Development

No branches or pull requests

6 participants