-
Notifications
You must be signed in to change notification settings - Fork 12.5k
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
A compiler option to enforce file extensions. #42813
Comments
Because nodejs requires file extensions for relative imports, |
In the meantime, you could use eslint-plugin-import's It would be nice if TypeScript could enforce this though. TypeScript should be able to detect simple runtime errors like not including a file extension in an import. |
I think this is becoming increasingly important. There has been a significant move towards ESM-only packages in the last few months. For example, I am using the How naive I was! My project built fine, only to fall over immediately when launched in Node. The problem? My ESM import paths absolutely must have After reading through the notorious #16577, I had the same thought as @trusktr. I'll tolerate spending a few hours to rewrite all my import paths with a Yes, you can set a config flag in VSCode, and add an ESLint rule. But not everyone uses VSCode, and some people will manage to avoid running ESLint. And that means that a catastrophic runtime exception will probably sneak into a production deployment at some point. Adding this flag or a new |
node-fetch just moved to pure ESM on v3.0.0-beta.10 too |
I am likewise here from https://blog.sindresorhus.com/get-ready-for-esm-aa53530b3f77#23d5 because |
I'm not crazy about this change, as I liked it when it inferred the extension automatically. Also, it feels weird to provide a .js file extension when I'm writing TypeScript files. However, this seems to be necessary for pure-ESModule packages, and after installing `markdown-table` I need to make these changes. [1]:https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c#faq [2]:microsoft/TypeScript#42813 [3]:https://www.typescriptlang.org/docs/handbook/module-resolution.html#classic [4]:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules
Random tip: if you happen to be using Webpack 5 or higher, it will automatically complain if you forgot a This leads to a temporary workaround: you can test your code by running Webpack on it, even if you just ignore the result, and you'll get errors on missing extensions. |
This should probably be closed by #44501, in my opinion. It doesn’t make sense to say “make me write file extensions” outside the broader context of a module resolution strategy where file extensions are required, and |
Does #44501 enforce the presence of file extensions or does it magically transpile to the correct import statement? I couldn't figure it out from skimming the PR. |
It enforces file extensions. TS will never rewrite an import declaration’s module specifier under any mode, and in Node’s ESM implementation, file extensions are required, therefore we must make you write them. |
Awesome. Sounds like this will work in browsers and support |
Closing since #44501 is in now. Use |
Has anyone successfully gotten ESLint to enforce the .js extension on .ts imports? I've tried using and it just says |
Using --moduleResolution with esnext still does solve the issue. Since awkward *js suffix is still needed when you importing TS file which is illogical. Just a a workaround for workaround.. |
This doesn't quite fix the problem though. If I have TSConfig for a browser environment, I would also need to set the It feels like there would need to be a way to opt into |
Can you clarify your setup a little bit? What tool is resolving node_modules packages to the |
@andrewbranch Sure! The setup is for a component library called Shoelace. https://github.com/shoelace-style/shoelace/ We have a library we import here called we import it here: and then in a PR I have with NodeNext, it requires this hacky workaround because it think its a Node import and not a "default" import. I was wrong about the "browser" export condition. The package doesnt appear to have a browser export conditional when examining the package as I initially thought, instead, it appears it to behave like a We are shipping unbundled ESModules to NPM for users to consume. Basically, when I change our TSConfig from the following: {
"target": "es2017",
"module": "es2020",
"moduleResolution": "Node",
} to the following: {
"target": "es2017",
"module": "NodeNext",
"moduleResolution": "NodeNext",
} That QRCreator.render fails with: and our ESLint ends up throwing 1000+ error for things like this:
Despite no errors with the previous setup. Let me know if there's anything else I can do to help clarify. |
What’s happening is that the qr-creator library is providing an ES module that TypeScript thinks is a CJS module, because Node.js would interpret it as a CJS module and crash if it tried to load that file. I think this is a subtle bug in qr-creator. Even though their code is DOM-dependent, they’re distributing their code via npm, which means they expect their consumers to have it in node_modules, so they would do well to conform to Node.js packaging conventions. Additionally, anyone who might want to import qr-creator into Node.js with jsdom for testing purposes is currently completely unable to do so. They should rename The reason we suggest using |
🤔 okay. That makes sense. I'm not sure what to make of my eslint errors, but that seems more easily fixed. It may just be a config issue with the typescript-eslint-parser. I'll see if I can make a PR to the qr-code repository. As for crashing node, there is a case for Jest, as well as Node-based SSR, so will be something we need to address. Thank you so much for your time and help. |
I’m happy to help advise on the qr-creator PR. Good luck though, because its last publish was 4 years ago 😐 |
Now that there is also |
What do you want from |
nodenext is enforcing file extensions, which is the thing you're asking for. I don't understand what's missing |
@roydukkey take a look at https://www.typescriptlang.org/docs/handbook/modules/guides/choosing-compiler-options.html#considerations-for-bundling-libraries
|
I think the issue @roydukkey has is similar to mine: I use libraries that require me to use "moduleResolution": "Bundler" because those libraries have extensionless import specifiers in their .d.ts files. That said, I still want to require of my code that it follows the rule of NodeNext: use extensions! In my opinion the answer is to use a linter -> eslint-plugin-import has a rule to enforce extensions, even if your tsconfig allows extensionless as a necessity for using libs that are published with extensionless import specifiers |
Extensions aren't required in |
They are—the way TS is interpreting this situation is that you’re running in Node.js, and you’re importing a library that has extensionless imports in its |
Yeah I've now tested this in a few projects and I can confirm what @andrewbranch said about this.. Sad truth is that a lot of my dependencies have extensionless imports in their .d.ts files so I'm basically always forced to use "Bundler" which is unfortunate because now I have to add some linting rule against extensionless imports, as TS now allows them under the "Bundler" leniency. I really do think this needs to be addressed in some way. |
I will add that sometimes this is easier said than done. Vue SFCs require bundling. |
Suggestion
A compiler option like
requireExtensions
would be great.🔍 Search Terms
typescript compiler require import extensions
✅ Viability Checklist
My suggestion meets these guidelines:
⭐ Suggestion
A compiler option like
requireExtensions
would enforce.js
extensions to make modules ESM-compatible without additional tooling, imports maps, or package.json exports fields.📃 Motivating Example
ESM ecosystem (Node, Webpack 5+, etc) follows the Node ESM standards. Tools like Webpack will throw a compile error on non-confoming ES Modules (when they don't conform to Node ESM spec), and Webpack full understands the package.json
exports
field when resolving modules for example.💻 Use Cases
This would help to enforce writing code that is more likely to work well in strict Node ESM environments.
In Webpack 5, importing TypeScript output code that does no include extensions (although TS gives no error) results in a compile error for packages with
"type": "module"
in their package.json during Webpack's resolution (it behaves identical to Node ESM).With
requireExtensions
set tofalse
, the following code would be valid:With
requireExtensions
set totrue
, the following code would be valid only ifmoduleResolution
is also set to"node"
:otherwise with a different value of
moduleResolution
it would probably need to beThe text was updated successfully, but these errors were encountered: