import-js / eslint-plugin-import

ESLint plugin with rules that help validate proper imports.
MIT License
5.57k stars 1.57k forks source link

`import/namespace` creates false positives for 'prettier' in v2.30.0 #3069

Closed marikaner closed 1 month ago

marikaner commented 1 month ago

Hey, I am using prettier within a generator cli. I am trying to upgrade to version 2.30.0 but it shows me the following error when I do: import * as prettier from 'prettier';: No exported names found in module 'prettier'.. When I import it with import { format } from 'prettier' it does not complain, proving that the name actually exists.

I am using prettier version 3.3.3 with CJS.

ljharb commented 1 month ago

hmm, i wonder if this is caused by ExportMap changes (cc @soryy708)

marikaner commented 1 month ago

I don't know if it helps, but it also reports for import prettier from 'prettier'; with esModuleInterop enabled for the rule import/default. I assume the same root cause.

ljharb commented 1 month ago

esModuleInterop must always be enabled, or else TS's module system is broken.

soryy708 commented 1 month ago

Is this a regression or is this a configuration error in relation to esModuleInterop?

ljharb commented 1 month ago

Since esModuleInterop only relates to tsconfig, and isn't part of this config at all, it seems like it'd be a regression.

soryy708 commented 1 month ago

@marikaner Is this about a TypeScript project? or just JavaScript? If TypeScript, what versions of @typescript-eslint/parser and eslint-import-resolver-typescript?

marikaner commented 1 month ago

Oh yes, it is a TypeScript project. We do not have these dependencies and now I wonder how this ever worked. After I added them we have a lot of other (legit) findings, but this one is gone. Thanks for your support!

andersk commented 1 week ago

This should be reopened, as it can be reproduced in a plain JavaScript project with ES modules:

eslint.config.mjs

import eslintImport from "eslint-plugin-import";

export default [
  eslintImport.flatConfigs.recommended,
  { languageOptions: { ecmaVersion: "latest" } },
];

foo.mjs

import * as prettier from "prettier";

(async () => {
  console.log(await prettier.format("x=1", { filepath: "test.js" }));
})();
$ node foo.mjs
x = 1;

$ npx eslint foo.mjs

/tmp/test/foo.mjs
  1:8   error  No exported names found in module 'prettier'         import/namespace
  4:30  error  'format' not found in imported namespace 'prettier'  import/namespace

✖ 2 problems (2 errors, 0 warnings)
ljharb commented 1 week ago

@andersk TS's module system is broken unless you're using esModuleInterop and synthetic imports. If you do that, what happens?

andersk commented 1 week ago

@ljharb There is no TS at all in my example.

ljharb commented 1 week ago

ah, i saw import * as and assumed TS, since there's not much reason to use that syntax otherwise. i believe it should work the same if you import prettier from 'prettier'?

Either way, if it's still a problem, please file a new issue and I'll do my best to look into it.

andersk commented 1 week ago

In general, a namespace import (import * as m) is only equivalent to a default import (import m) when importing a CommonJS module. Some ESM packages arrange to export everything both ways (perhaps for backwards compatibility with previous CommonJS versions) but that is not required.

In any case, I get errors both ways, as detailed in my new issue: