Skip to content

Default imports don't work with moduleResolution=node16 #53349

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

Closed
tpluscode opened this issue Mar 19, 2023 · 8 comments
Closed

Default imports don't work with moduleResolution=node16 #53349

tpluscode opened this issue Mar 19, 2023 · 8 comments
Labels
External Relates to another program, environment, or user action which we cannot control.

Comments

@tpluscode
Copy link

tpluscode commented Mar 19, 2023

Bug Report

🔎 Search Terms

node16 default export

🕗 Version & Regression Information

I saw this in various versions on 4.8, 4.9 and 5.0 RC

💻 Code

I import modules which are typed in DT. For example

import namespace from "@rdfjs/namespace";
const foo = namespace(/* ... */)

The type declaration is

export default function namespace<TermNames extends string = string>(/* ... */): Whatever

Here's a reproduction: https://gist.github.com/tpluscode/8d1bfc9737f82f5005a5849e42f8f297

🙁 Actual behavior

When I set moduleResolution = "node16" Typescript complains with TS2349: This expression is not callable..

The error goes away with moduleResolution = "node". Also tsc stops showing the error when I add .default, which is wrong and will fail at runtime

import namespace from "@rdfjs/namespace";
-const foo = namespace(/* ... */)
+const foo = namespace.default(/* ... */)

🙂 Expected behavior

There should be no error

@tpluscode tpluscode changed the title Default imports don't with moduleResolution=node16 Default imports don't work with moduleResolution=node16 Mar 20, 2023
@jakebailey
Copy link
Member

jakebailey commented Mar 22, 2023

I'm pretty sure the the type package is wrong; add "type": "module" to @types/rdfjs__namespace and it's a function. Generally, the types package should be matching upstream.

@RyanCavanaugh RyanCavanaugh added the External Relates to another program, environment, or user action which we cannot control. label Mar 22, 2023
@tpluscode
Copy link
Author

You are right @jakebailey. Thank you for your help

@magiclen
Copy link

magiclen commented May 4, 2023

I encountered this issue with pino and pino-pretty which are CommanJS packages. So, setting "type": "module" in package.json is the only one solution for now? That would be very inconvenient.

@tpluscode
Copy link
Author

Probably not. As mentioned above

the types package should be matching upstream

Thus, you'd only add type: module if the pino and pino-pretty had that in their respective package.jsons.

@magiclen
Copy link

magiclen commented May 4, 2023

pino and pino-pretty uses "type": "commonjs" in their package.jsons. I use "type": "module" and "moduleResolution": "node16" in my project. As you mentioned above, I had better change my type to commonjs? But I want to use ESM...

If I use "moduleResolution": "node", I can write the code like below

import pino from "pino";
import pinoPretty from "pino-pretty";

If I use "moduleResolution": "node16", I need to write the code like below

import { pino } from "pino";
import { PinoPretty as pinoPretty } from "pino-pretty";

It's weird. Isn't it a bug?

@tpluscode
Copy link
Author

This issue was only related to @types/* packages.

In the case of pino, it appears that the types it publishes are not accurate. I have seen this often in types packages too, where the d.ts is written to represent ESM and not CJS. The authors of pino should adjust their index.d.ts to be something like

declare const Module: typeof pino & {
    pino: typeof pino
}

export = Module

Go ahead and share this repo with pino authors: https://github.com/tminuscode/pino-types

@mohd-akram
Copy link

mohd-akram commented Mar 12, 2024

I think this issue should be re-opened. I'm running into the same thing. This is my setup:

package.json:

{
  "type": "module",
  "devDependencies": {
    "@types/react": "^18.2.65",
    "typescript": "^5.4.2"
  },
  "dependencies": {
    "next": "^14.1.3"
  }
}

tsconfig.json:

{
  "compilerOptions": {
    "module": "Node16",
    "jsx": "preserve"
  }
}

index.tsx:

import Head from 'next/head.js';
<Head><title>Hello</title></Head>;

Running node_modules/.bin/tsc (version 5.4.2) yields:

index.tsx:2:2 - error TS2604: JSX element type 'Head' does not have any construct or call signatures.

2 <Head><title>Hello</title></Head>
   ~~~~

index.tsx:2:2 - error TS2786: 'Head' cannot be used as a JSX component.
  Its type 'typeof import("/private/tmp/ts-test/node_modules/next/head")' is not a valid JSX element type.

2 <Head><title>Hello</title></Head>
   ~~~~


Found 2 errors in the same file, starting at: index.tsx:2

The types are correct in Next:

node_modules/next/head.d.ts:

import Head from './dist/shared/lib/head'
export * from './dist/shared/lib/head'
export default Head

node_modules/next/dist/shared/lib/head.d.ts:

import React from 'react';
export declare function defaultHead(inAmpMode?: boolean): JSX.Element[];
/**
 * This component injects elements to `<head>` of your page.
 * To avoid duplicated `tags` in `<head>` you can use the `key` property, which will make sure every tag is only rendered once.
 */
declare function Head({ children }: {
    children: React.ReactNode;
}): import("react/jsx-runtime").JSX.Element;
export default Head;

@RyanCavanaugh
Copy link
Member

@mohd-akram please open a new issue with the "module resolution" template

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
External Relates to another program, environment, or user action which we cannot control.
Projects
None yet
Development

No branches or pull requests

5 participants