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

TypeScript import @google-cloud/tasks error #5683

Closed
dipbhi opened this issue Sep 14, 2024 · 5 comments
Closed

TypeScript import @google-cloud/tasks error #5683

dipbhi opened this issue Sep 14, 2024 · 5 comments

Comments

@dipbhi
Copy link

dipbhi commented Sep 14, 2024

Since this change, import is broken from TypeScript with NodeNext.

https://github.com/googleapis/google-cloud-node/blame/6773a05ce96d64e4a1034e8b63ef6ec0d6688fd2/packages/google-cloud-tasks/package.json#L14


Code generating the error:

import { CloudTasksClient } from "@google-cloud/tasks";

Error message:

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("@google-cloud/tasks")' call instead.


tsconfig.json:

{
    "compilerOptions": {
        "module": "NodeNext",
        "noImplicitReturns": true,
        "noUnusedLocals": true,
        "outDir": "lib",
        "skipLibCheck": true,
        "sourceMap": true,
        "strict": true,
        "target": "ESNext"
    },
    "compileOnSave": true,
    "include": [
        "src"
    ]
}

Workaround 1: Downgrade to 4.0.1.
Workaround 2: Use dynamic import.

@dipbhi
Copy link
Author

dipbhi commented Sep 17, 2024

The Workaround 1 is posing another challenge. Fix for #5000 requires upgrading the @google-cloud/tasks to 5.2.1+, but you can't build it above 4.0.1. 😠

@sofisl
Copy link
Contributor

sofisl commented Sep 20, 2024

The reason for this is that @google-cloud/tasks is now published as a dual-format ESM and CJS module as of 5.0. Using NodeNext tells the compiler to import as ESM if you're using imports. One option is to use dynamic imports, like you said, or you can just require tasks, it will use CJS.

@sofisl sofisl closed this as completed Sep 20, 2024
@sofisl
Copy link
Contributor

sofisl commented Sep 20, 2024

@danielbankhead as FYI for future notes to better explain this feature.

@dipbhi
Copy link
Author

dipbhi commented Sep 21, 2024

I understand what is causing it, but the problem is that it's happening. None of the other @Google-Cloud packages have this problem (that I know of). @google-cloud/tasks didn't have this problem until recently either. A different design or way to export multiple format should be considered. I have started using dynamic imports as a workaround but regular import at the top of the file would be a much better option. Thank you.

@grainrigi
Copy link

The reason for this is that @google-cloud/tasks is now published as a dual-format ESM and CJS module as of 5.0. Using NodeNext tells the compiler to import as ESM if you're using imports. One option is to use dynamic imports, like you said, or you can just require tasks, it will use CJS.

This is not correct. Typescript resolves the import for @google-cloud/tasks to the cjs bundle because it is imported from a CommonJS context, so require will be emitted in the compiled Javascript code if the error does not exist. Typescript is warning that we are requireing the package because the cjs bundle looks like an ESM module on the Typescript side.

Reason that typescript misunderstands the module type is:

  • Typescript considers build/cjs/src/index.d.ts as the entrypoint (it doesn't care that the corresponding Javascript file (build/cjs/src/index.cjs) has cjs extension)
  • Typescript infers the NodeFormat of index.d.ts to be ESM because the nearest package.json has "type":"module" in it.

So this can be resolved if we correctly tell the NodeFormat of build/cjs/src/index.d.ts to Typescript. This can be done by one of the following:

  • rename index.d.ts to index.d.cts
    • you have to rewrite the corresponding references in the types field and the exports field of the package.json
  • place package.json with {"type":"commonjs"} in build/cjs/src
    • This might change the behavior of Node.js if some .js files exist under build/cjs/src since it will no longer be treated as ESM

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants