Skip to content

Allow mapping of expected extensions in import/extension rule #2030

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
pwhissell opened this issue Apr 23, 2021 · 13 comments
Closed

Allow mapping of expected extensions in import/extension rule #2030

pwhissell opened this issue Apr 23, 2021 · 13 comments

Comments

@pwhissell
Copy link

pwhissell commented Apr 23, 2021

Context:

I have a typescript project for a node application using ESM (ecmascript modules)
Because node requires that file extensions be specified for relative imports when using esm, typescript files must import relative modules with the ".js" extension. Using a typescript resolver enables linting to resolve these modules well, but when trying to enforce file extensions using the import/extensions rule, the linter expects the file extensions to be ".ts".
I would like a way to configure the rule to assert that extension rather be ".js"

Repro :

applying linting rules

npx eslint .

in the following gist
https://gist.github.com/pwhissell/165232e5fdd62641efa771f000f1e651

Current output:

1:31 error Missing file extension "ts" for "./other.js" import/extensions 2:33 error Missing file extension "ts" for "./another" import/extensions

Expected:

2:33 error Missing file extension "js" for "./another" import/extensions

Example usage:

rules: { import/extensions: ["error", {"ts", "ignorePackages", "js"}] #<-- this would tell the linter that modules defined in ts files should always be imported with the .js extension }

@ljharb
Copy link
Member

ljharb commented Apr 23, 2021

I'm a bit confused. You're using TypeScript and native ESM?

Native ESM should be .mjs files; I strongly suggest avoiding type: "module" as it causes nothing but problems.

@pwhissell
Copy link
Author

I use Typescript for strict syntactical static validation of my code. But I want to leverage ecmascript functionalities like "top-level await", "block modules" and any modern module functionalities inside my node application. Therefore I choose to have it transpile to ESNEXT and use ESM. Thankfully nodejs is subscriibing to TS39's ES proposals as well as the Typescript team. So having it work is not a problem (as you can see in my gist). By browsing Typescript's repo you can find a lot of github issues like this one that describe a displeasing loophole in how modules are transpiled. Thiis issue along with a lot of ESM / CJS miss-interpretations would be with this issue.

Native ESM should be .mjs files; I strongly suggest avoiding type: "module" as it causes nothing but problems.
saying "don't adopt 'type: "module"' is like saying "don't empbrace ESNEXT"

I added an example expected usage if that could help.

@ljharb
Copy link
Member

ljharb commented Apr 23, 2021

You can use those features regardless of your transpilation target; there's no reason you need to use native ESM for that.

@ljharb
Copy link
Member

ljharb commented Apr 23, 2021

I'm still a bit confused. It sounds like the TS resolver is the problem here, not the linting rule?

@pwhissell
Copy link
Author

pwhissell commented Apr 24, 2021

You can use those features regardless of your transpilation target; there's no reason you need to use native ESM for that.

I'm sure your experience at tc39 gave you lots of understanding about ecmascript ambitions. Perhaps you should read a little on nodejs, esm and commonjs modules before making such claims.

here are a couple articles, posts and issues that may be helpfull

I'm still a bit confused. It sounds like the TS resolver is the problem here, not the linting rule?

It sounds like you haven't taken a look at my gist, maybe you missed the link
https://gist.github.com/pwhissell/165232e5fdd62641efa771f000f1e651

the resolver resolves the module well (wether the ".js" extension is present or not) but the "extension" linting rule enforces a .js extension

should i draft a PR?

@ljharb
Copy link
Member

ljharb commented Apr 24, 2021

I was in the node modules working group, I’m quite informed, thanks, and your hostility is not appreciated.

You can transpile to CJS and take advantage of all those features, full stop, regardless of whether you’re using TS or not. I’m aware there’s issues when using TS and attempting to work with native ESM, which is an example of why I’m suggesting avoiding native ESM for awhile.

@ljharb
Copy link
Member

ljharb commented Apr 24, 2021

If you want the extensions rule to be configured for a specific extension, you can use eslint’s overrides config to make that setting apply only to .ts files. I’ll try not to be condescending while i point you to eslint’s documentation for that.

@ljharb ljharb closed this as completed Apr 24, 2021
@pwhissell
Copy link
Author

You can transpile to CJS and take advantage of all those features, full stop, regardless of whether you’re using TS or not

again, that isn't true nodejs doesn't and will probably never support top-level await when using CJS

you can use eslint’s overrides config to make that setting apply only to .ts files

I don't think I managed to convey my request correctly. Ill make a PR tomorrow, I think things will be clearer from there. Discussions just as well

@ljharb
Copy link
Member

ljharb commented Apr 24, 2021

Top-level await doesn’t work directly in CJS, of course; that’s not what i said. It can be transpiled to something else so that you can use it.

@pwhissell
Copy link
Author

@pwhissell
Copy link
Author

I drafted a quick PR that still requires more unit testing and for which comments would be well appreciated

@berniegp
Copy link

Native ESM should be .mjs files; I strongly suggest avoiding type: "module" as it causes nothing but problems.

@ljharb do you have any sources that tell more about these problems? I'm trying to figure out the best way forward to migrate a package to ESM and type: "module" seemed convenient until I randomly stumbled on this issue. Many thanks!

@ljharb
Copy link
Member

ljharb commented Mar 17, 2022

@berniegp the only things type module do are 1) make .js be ESM instead of CJS, which breaks compatibility with older nodes that assume .js is always CJS; 2) in some cases shuts off normal node resolution of extensions and index; 3) breaks tooling (like this plugin, which uses resolve) that doesn't yet support exports or type.

If you just name your ESM files .mjs, everything works fine, and you don't run into any of these problems.

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

Successfully merging a pull request may close this issue.

3 participants