Module resolution: tsgo resolves package.json `exports` conditions differently than `tsc` and errors
Opened this issue · 4 comments
Corsa interprets exports conditions in package.json differently than Strada does, and throws errors that Strada does not throw. Using module/moduleResolution of nodenext.
I believe this is the same issue as #916, which was closed lacking a reproduction.
The exports looks like:
"exports": {
".": {
"require": "./src/index.js",
"import": "./src/index.mjs",
"default": "./src/index.mjs"
}
}in a commonjs scope (no "type": "module")
Steps to reproduce
Repository: https://github.com/controversial/tsgo-exports-resolution-repro/
Run pnpm install; then run tsgo inside packages/my-app (which imports from packages/my-package).
Behavior with typescript@5.8
No error running tsc
Behavior with tsgo
test.ts:1:26 - error TS2497: This module can only be referenced with ECMAScript imports/exports by turning on the 'allowSyntheticDefaultImports' flag and referencing its default export.
1 import { myExport } from '@pkg/my-package';
~~~~~~~~~~~~~~~~~
Found 1 error in test.ts:1
The error
This module can only be referenced with ECMAScript imports/exports by turning on the 'allowSyntheticDefaultImports' flag and referencing its default export.
is misleading because allowSyntheticDefaultImports is already enabled.
Importing the “default export” instead of the named export instead causes the error
Module '"/path/to/my-package/src/index"' has no default export.
(closed by accident, sorry)
Something is wrong here since the error text doesn’t make sense, but when you run your test file in Node.js, you get the warning:
❯ node test.ts
example
(node:82763) [MODULE_TYPELESS_PACKAGE_JSON] Warning: Module type of file:///Users/andrew/Developer/microsoft/eg/tsgo-exports-resolution-repro/packages/my-app/test.ts is not specified and it doesn't parse as CommonJS.
Reparsing as ES module because module syntax was detected. This incurs a performance overhead.
To eliminate this warning, add "type": "module" to /Users/andrew/Developer/microsoft/eg/tsgo-exports-resolution-repro/packages/my-app/package.json.
(Use `node --trace-warnings ...` to show where the warning was created)
TypeScript does not support this reparsing, so we can’t guarantee accurate behavior if you’re relying on it. We will assume this is CommonJS and might give you different results. (That said, in this example, the CommonJS interpretation of test.ts should still be valid under --module nodenext, but in general, using ESM without marking it as ESM could lead to a bad time.)
In practice, in our repository, the test.ts file is a vite.config.ts, which I believe gets transpiled by vite before executing, so I guess that’s why we don’t see the node warning at runtime
point taken that this setup isn‘t exactly correct/optimal, but we noticed it as a breaking behavioral difference when trying out tsgo
thanks for looking into it!