-
Notifications
You must be signed in to change notification settings - Fork 274
Closed
Description
Describe the bug
Getting
main.ts:1:23 - error TS1471: Module 'csv-parse' cannot be imported using this construct. The specifier only resolves to an ES module, which cannot be imported synchronously. Use dynamic import instead.
when trying to import in a project with moduleResolution: node16
.
To Reproduce
package.json
{
"dependencies": {
"csv-parse": "5.3.0",
"typescript": "4.7.4"
}
}
tsconfig.json
{
"compilerOptions": {
"moduleResolution": "Node16"
}
}
main.ts
import { parse } from 'csv-parse';
and then run:
tsc
Output I get:
$ tsc
main.ts:1:23 - error TS1471: Module 'csv-parse' cannot be imported using this construct. The specifier only resolves to an ES module, which cannot be imported synchronously. Use dynamic import instead.
1 import { parse } from 'csv-parse';
~~~~~~~~~~~
Found 1 error in main.ts:1
Additional context
My intent in this example is to import csv-parse using require, but typescript seems to think this library only exposes esm modules.
Typescripts esm support is not without controversies. One of them is that they are more strict about the location of .d.ts
files: microsoft/TypeScript#49160 . The most straightforward solution seems to be just duplicating the type definitions beside all entry points, but there might be better ways I am not aware of.
Activity
wdavidw commentedon Aug 2, 2022
In demo/ts-module-node16/tsconfig.json, we used
module
instead ofmoduleResolution
:Otherwise, please look at the demo and try to find what's different.
sorgloomer commentedon Aug 2, 2022
Unfortunately having
moduleResolution: node16
ornodenext
is a hard constraint for us, as this is the only setting of typescript that enables us to use dynamicimport()
statements that wouldn't get transpiled intorequire()
s. Dynamic imports would be our vehicle to deal with other esm-only modules.The difference with the new moduleResolutions settings is, to my understanding, typescript now only considers the
"exports"
entry of the package.json, and does not consider the "types" entry anymore. In microsoft/TypeScript#49160 they claim these typing issues to be due to misconfigured third party packages.I tried all the typescript configuration combinations, unfortunately none of them is covering all the usecases.
wdavidw commentedon Aug 3, 2022
Having a hard time understanding the exact need. I am not a TS user myself, just trying to help. Could you create a demo similar to ts-module-node16. Fork the repository, duplicate the
./demo/ts-module-node16
folder, modify it to suit your need and push the changes in your fork. This would help a lot.Note, my initial understand was wrong. I have tried to use dynamic import with
module
with success.sorgloomer commentedon Aug 3, 2022
Sure, thanks for considering my case! I am off for a couple of weeks, after that I'll create the fork and will attempt to alter the configuration to match my needs without breaking any of the demos. Do you mind if I keep the ticket open until then?
wdavidw commentedon Aug 3, 2022
No worry, I am myself on holidays as well. In order to not break any demo, just
cp -rp ./demo/ts-module-node16 ./demo/ts-moduleresolution-node16
.mantljosh commentedon Oct 12, 2022
I'm pretty sure the issue here is the
type: "module"
in package.json which makes TS think that everything in the package is going to be ESM (even though there is CJS as specified in theexports
)wdavidw commentedon Oct 12, 2022
Hum, that is an interesting possibility.
acidoxee commentedon Oct 29, 2022
I'm having a similar problem as well when using those CSV packages in a CJS context. I'm still not sure that's the whole story, but if I got this right, the issue is that
.cjs
files inpackages/*/dist/cjs
MUST have a sibling.d.cts
declaration file. Usingexports.*.types
fields inpackage.json
and pointing them to.d.ts
definitions does absolutely nothing, since only.d.cts
extensions would work because of the.cjs
extension of CJS files.To reproduce the problem, just do this: https://github.com/acidoxee/node-csv/commit/4e6cf591715a8dc8823989e435b5c079d6ad56a8, and look at the error on the import here: https://github.com/acidoxee/node-csv/blob/4e6cf591715a8dc8823989e435b5c079d6ad56a8/demo/ts-module-node16/lib/stringify.ts#L3.
I don't think there's any use to forcing those
exports.*.types
anyway (like it was recently added in this commit), since the declarations already seem to always be adjacent to their sibling JS files.The only appropriate fix here seems to yield matching
.d.ts
,.d.cts
and/or.d.mts
declaration files next to each JS file with a.js
,.cjs
and/or.mjs
extension respectfully.See this comment and its whole thread which seems to confirm this behavior.
wdavidw commentedon Nov 8, 2022
Does having both the "module" and "moduleResolution" set to "Node16" could resolve the issue ?
wdavidw commentedon Nov 8, 2022
Otherwise, could someone reproduce the issue in a branch inside a dedicated "./demo/{package}". Reproducing the issue would help finding a solution
LinusU commentedon Nov 9, 2022
With #368 merged, the following settings work for us:
tsconfig.json
package.json
my-file.ts
wdavidw commentedon Nov 9, 2022
OK, then let's close it.
acidoxee commentedon Dec 23, 2022
That's great for ESM! Although when consuming
csv-parse
andcsv-stringify
from a CJS module, the problem I've described previously is still present AFAICT.When writing
import { parse } from 'csv-parse'
from a CJS module with"module": "Node16"
in its corresponding TS config, theexports
map resolves to"require": "./dist/cjs/index.cjs"
for the runtime, but to"types": "./lib/index.d.ts"
for the types, which do not have the proper.d.cts
extension that's expected for TS to understand it's importing a CJS file (see my previous comment and the TS 4.7 announcement). I believe the reason is that the"type": "module"
field incsv-parse
'spackage.json
makes TS infer an ESM context everywhere, except if specifically told otherwise through a.d.cts
extension on the declaration file.Wouldn't there be a way for you to generate those declaration files in
dist/cjs
with a.d.cts
extension instead of.d.ts
? From my understanding, if you did that, you could (and even should) also entirely remove theexports.*.types
field in the export map, since declarations are already adjacent to the JS files, and all imports would work great, whether they're done from ESM or CJS.wdavidw commentedon Dec 26, 2022
If you provide me with a project example illustrating the issue inside the "demo" folder, then I'll be happy to generate the ".d.cts" files.
jonmast commentedon Feb 7, 2023
@wdavidw I've added a demo illustrating the issue: https://github.com/jonmast/node-csv/tree/master/demo/ts-moduleresolution-node16-cjs
Running:
npx run typecheck
in that directory should return the error.I believe this happens with the combination of
module: commonjs
,moduleResolution: node16
(in tsconfig), andmodule: false
(in package.json). The fix is to use.d.cts
files as @acidoxee said.acidoxee commentedon Feb 7, 2023
Thanks for the demo @jonmast, and sorry for not getting back to you @wdavidw!
Another thing I haven't tried is putting the
exports.*.types
key as the first key in the object. This is something that's mentioned in the TS 4.7 announcement here:I'm not sure if this really has an effect or not, but might as well follow their instructions on that matter.
wdavidw commentedon Feb 7, 2023
Validated, could you create a merge request with the demo folder, I'll merge it and make the changes in the mean time
jonmast commentedon Feb 7, 2023
I've opened PR #377, thanks for the speedy response @wdavidw!
wdavidw commentedon Feb 7, 2023
Could we rename the demo with a short name, also, I don't think node 16 has anything to do with test, I tested the same behavior with Node 18 and 19 and tsconfig mention
module
ascommonjs
astarget
ases5
.jonmast commentedon Feb 7, 2023
Sure, I can rename it.
You are correct that the error isn't node version specific, it is from Typescript's "node16" resolver which was built to be compatible with the new module resolver in node 16 but also applies to newer releases.
fix: support ts node16 resolution in cjs (#354)
wdavidw commentedon Feb 8, 2023
The following packages were updated:
wdavidw commentedon Feb 8, 2023
I renamed it to "ts-cjs-node16"
ReactApolloRawPluginConfig
under"moduleResolution": "node16"
dotansimha/graphql-code-generator-community#513