You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Compiled JavaScript import is missing file extension #40878
The compiler generates JavaScript "which runs anywhere JavaScript runs: In a browser, on Node.JS or in your apps" (according to the TypeScript homepage). For example, it would be valid to create two files as follows; main.js:
(More generally, the expected behavior is that the module specifier in the generated import must match the filename chosen for the generated dependency. For example, it would also be valid for the compiler to generate a file dep.xyz, if it also generated import ( foo } from './dep.xyz'.)
Actual behavior:
As above, except that in main.js, the import URL does not match the filename chosen by the compiler for the generated dependency; it is missing the file extension:
import{foo}from'./dep';
When executing main.js in the browser, it requests the URL ./dep, which is a 404. This is expected, as the correct relative URL would be ./dep.js.
Related Issues:#13422, voluntarily closed by the reporter for unknown reasons
TypeScript doesn't modify import paths as part of compilation - you should always write the path you want to appear in the emitted JS, and configure the project as necessary to make those paths resolve the way you want during compilation
Reacted by Thomas Allmer
Reacted by Manuel Astudillo, Remi Cattiau, Aurélien Altarriba, Thundercraft5, Alexis Bouhet, Jeff Hull, Philipp G., Ivan Fedulov, pcd444, Marcus Lima and 29 more
Thanks Ryan Cavanaugh (@RyanCavanaugh)! Do you mean I should write import { foo } from './dep.js' in my source main.ts? That does actually seem to work! In that the compiler uses './dep.ts' to find the types of variables exported.
However, I find this surprising, because
The recommendation everywhere else in TypeScript docs is to omit the file extension.
If I try to import from './dep.ts', the compiler gives me error TS2691: An import path cannot end with a '.ts' extension. Consider importing './dep' instead. So apparently it's not possible to generate JavaScript imports that end in .ts?
The module resolution docs don't say what's going on here. What logic makes this work? Is there a special case for .js, which is mapped to .ts?
I can't find a rationale for this design anywhere.
Reacted by RevealedFrom, Cuixiping, ryancwalsh, David Powell, Lianghua, Tomasz Robaczewski, gudh, Timsonrobl, abdessamad bourhjoul, Igor and 58 more
Reacted by Faber-smythe, Nathan Hayfield and Weiyuan Wu
TS never takes an existing valid JS construct and emits something different, so this is just the default behavior for all JS you could write. Module resolution tries to make all of this work "like you would expect"
Reacted by dominictobias, Manuel Astudillo, Philipp G., pcd444, Adam Shaylor, Nick Chevsky, Donato Monzón, Vladislav Suchkov, Wormss9, The Potato Chronicler and 12 more
Ryan Cavanaugh (@RyanCavanaugh) that principle makes sense. My remaining confusion then is why the docs and compiler encourage omitting the file extension, if "you should write the import path that works at runtime". Maybe this encouragement is designed for a JS runtime that demands that you omit the file extension. But the runtimes I'm aware of are browser, ES modules, and Node.js, none of which make this demand.
Reacted by ryancwalsh, Jos de Jong, David Powell, ritmos, Jonathan Sharman, Andrei Dumitrescu, Gareth Chen, Zachary Raineri, WesMC, dominictobias and 9 more
Ryan Cavanaugh (@RyanCavanaugh) Writing "./dep.js" doesn't sound logical. The file dep.js does not exist in the Typescript universe. This approach requires the coder to know the exact complied output and be fully aware of the compiled environment. It's like having to know the CIL outputted and modify it here and there in order to code in C# successfully. Isn't the whole idea of Typescript to abstract away Javascript?
import { foo } from "./dep" is legitimate Typescript, and it provides the information for Typescript to resolve all that is needed to type check and make the code compile successfully. So, the compiled output should work. Typescript should not be generating syntactically incorrect Javascript.
IMHO, this issue should be a bug.
Reacted by Jochen Kühner, Cuixiping, ryancwalsh, David Powell, artem avetisyan, Manuel Vila, Jeremy Stover, Andrés Correa Casablanca, Tim, Tomasz Robaczewski and 108 more
Reacted by ELLIOTTCABLE
Reacted by Lewis, Andrés Correa Casablanca, Dan Rivett, dominictobias and Peter Strøiman
The whole idea of TypeScript is to add static types on top of JavaScript, not to be a higher-level language that builds to JS. The C# / IL comparison is not apt at all.
There's literally no line of undownleveled JavaScript code you can write where TS intercepts some string in it and changes it to be something else. This is 100% consistent with TS behavior in every other kind of JS construct; it would be frankly bizarre to have import paths be the one thing that we decide to go mess with.
Reacted by Reece Como, Nikhil and Tristan Hessell
Reacted by Dan Rivett, matthelliwell2, Hunter Kohler, WesMC, Martin Zaloudek, mitsukuri, Matt McHenry, Sobri Che Puteh, dominictobias, Hulk and 22 more
problem is, ts does not only need to add '.js', there are complexer resolution strategies.
i would like it, if there would be a way of calling a plugin after transpilation had been done, so I could fix the import names with that.
I know I could use a bundler / build system, but we ship directly the code typescript generates, without an additional build step. at the moment we fix the import path's in our own webserver.
This issue has been marked 'Working as Intended' and has seen no recent activity. It has been automatically closed for house-keeping purposes.
Reacted by Gerke van Garderen, Lewis, beary, nuts-n-bits, Lianghua, Jeremy Stover, Vitaly Pinchuk, Tomasz Robaczewski, realkit, abdessamad bourhjoul and 77 more
Here is the "bug" I submitted to the "vscode" repo, and that team rejected it and said that I should submit to the "TypeScript" repo here: microsoft/vscode#108872
It seems that people trying to write TypeScript in VSC face this dilemma of choosing between:
VSC shows an error (red underline), but the code works, or:
If we follow the VSC error tooltip's suggestion, it will "resolve" the error in the editor, but then the code won't run.
I'm getting this error and don't understand why:
An import path cannot end with a '.ts' extension. Consider importing '_______' instead. ts(2691)
So far, I have had success with Ryan Cavanaugh (@RyanCavanaugh)'s suggestion to "always write the path you want to appear in the emitted JS, and configure the project as necessary to make those paths resolve the way you want during compilation".
But I am still confused because this advice contradicts the compiler and docs and ecosystem, which all encourage omitting file extensions.
Reacted by Jeff Hull, pcd444, Adam Shaylor, Nick Chevsky, Vladislav Suchkov, Lokeshwar Tailor, The Potato Chronicler and PixLSteam
Yeah that doesn't feel right. I really don't understand. I can't think of any principle where it would make sense to throw a prominent red error for something legal.
Same issue here. Adding a .js in the import inside a TypeScript file does allow to compile it with the TypeScript compiler and will output files with working ESM imports.
However, when I add .js extensions on the imports, I can't get testing working. Tried with Mocha and Jest, but no luck so far: they complain the files with .js extension don't exist, which is correct, those files don't exist since they actually have a .ts extension.
I would love to see the TypeScript compiler add .js extenstions on imports when the output is esm/es2015.
Reacted by Lianghua, Andrés Correa Casablanca, Gareth Chen, iugo, Andrii Oriekhov, Dan Rivett, Nathan Glenn, Kurtis Golding, Alex Richardson, Sobri Che Puteh and 13 more
Reacted by Elhamuddin, Jose Antonio Felix and The Potato Chronicler
But wasn't it fixed?
To my greatest surprise, in my latest project, I'm using relative imports
in TypeScript without a file extension and the emitted JS just works!
On Thu, 3 Nov 2022, 15:51 Claudio Cicali, ***@***.***> wrote:
So weird. In VSC if you Cmd+click on a import something from
'something.js'; you'll get to the .ts file, like VSC knows that this
issue exists and "fixes it".
—
Reply to this email directly, view it on GitHub
<#40878 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AALESE7ZQOKDR7GJ3NTCYTTWGPGPFANCNFSM4SA23LJQ>
.
You are receiving this because you were mentioned.Message ID:
***@***.***>
So weird. In VSC if you Cmd+click on a import something from 'something.js'; you'll get to the .ts file, like VSC knows that this issue exists and "fixes it".
This has nothing to do with VSC and also works in every other editor with the typescript LSP. Completely unrelated to this issue.
Just leaving my +1 here... can't believe this is still an issue.
Would be as simple as to allow using .ts extensions and then transform them into .js.
This would make everyone happy: hundreds of people asking for it and TS maintainers because TS principles will not be affected this way (read this comment).
Activity
RyanCavanaugh commentedon Oct 1, 2020
TypeScript doesn't modify import paths as part of compilation - you should always write the path you want to appear in the emitted JS, and configure the project as necessary to make those paths resolve the way you want during compilation
jameshfisher commentedon Oct 1, 2020
Thanks Ryan Cavanaugh (@RyanCavanaugh)! Do you mean I should write
import { foo } from './dep.js'in my sourcemain.ts? That does actually seem to work! In that the compiler uses'./dep.ts'to find the types of variables exported.However, I find this surprising, because
'./dep.ts', the compiler gives meerror TS2691: An import path cannot end with a '.ts' extension. Consider importing './dep' instead. So apparently it's not possible to generate JavaScript imports that end in.ts?.js, which is mapped to.ts?RyanCavanaugh commentedon Oct 1, 2020
TS never takes an existing valid JS construct and emits something different, so this is just the default behavior for all JS you could write. Module resolution tries to make all of this work "like you would expect"
See also #15479 (comment)
jameshfisher commentedon Oct 1, 2020
Ryan Cavanaugh (@RyanCavanaugh) that principle makes sense. My remaining confusion then is why the docs and compiler encourage omitting the file extension, if "you should write the import path that works at runtime". Maybe this encouragement is designed for a JS runtime that demands that you omit the file extension. But the runtimes I'm aware of are browser, ES modules, and Node.js, none of which make this demand.
RevealedFrom commentedon Oct 2, 2020
Ryan Cavanaugh (@RyanCavanaugh) Writing "./dep.js" doesn't sound logical. The file dep.js does not exist in the Typescript universe. This approach requires the coder to know the exact complied output and be fully aware of the compiled environment. It's like having to know the CIL outputted and modify it here and there in order to code in C# successfully. Isn't the whole idea of Typescript to abstract away Javascript?
import { foo } from "./dep"is legitimate Typescript, and it provides the information for Typescript to resolve all that is needed to type check and make the code compile successfully. So, the compiled output should work. Typescript should not be generating syntactically incorrect Javascript.IMHO, this issue should be a bug.
RyanCavanaugh commentedon Oct 2, 2020
The whole idea of TypeScript is to add static types on top of JavaScript, not to be a higher-level language that builds to JS. The C# / IL comparison is not apt at all.
There's literally no line of undownleveled JavaScript code you can write where TS intercepts some string in it and changes it to be something else. This is 100% consistent with TS behavior in every other kind of JS construct; it would be frankly bizarre to have import paths be the one thing that we decide to go mess with.
jogibear9988 commentedon Oct 2, 2020
problem is, ts does not only need to add '.js', there are complexer resolution strategies.
i would like it, if there would be a way of calling a plugin after transpilation had been done, so I could fix the import names with that.
I know I could use a bundler / build system, but we ship directly the code typescript generates, without an additional build step. at the moment we fix the import path's in our own webserver.
typescript-bot commentedon Oct 4, 2020
This issue has been marked 'Working as Intended' and has seen no recent activity. It has been automatically closed for house-keeping purposes.
ryancwalsh commentedon Oct 18, 2020
Ryan Cavanaugh (@RyanCavanaugh) Jim Fisher (@jameshfisher) I was about to post a new bug about TypeScript but then the template encouraged me to search again, and I found this issue, which might be similar enough.
But I'm still confused, even reading above.
Here is the "bug" I submitted to the "vscode" repo, and that team rejected it and said that I should submit to the "TypeScript" repo here: microsoft/vscode#108872
It seems that people trying to write TypeScript in VSC face this dilemma of choosing between:
I'm getting this error and don't understand why:
See also: #11235 (comment)
jameshfisher commentedon Oct 19, 2020
So far, I have had success with Ryan Cavanaugh (@RyanCavanaugh)'s suggestion to "always write the path you want to appear in the emitted JS, and configure the project as necessary to make those paths resolve the way you want during compilation".
But I am still confused because this advice contradicts the compiler and docs and ecosystem, which all encourage omitting file extensions.
ryancwalsh commentedon Oct 22, 2020
Yeah that doesn't feel right. I really don't understand. I can't think of any principle where it would make sense to throw a prominent red error for something legal.
josdejong commentedon Nov 5, 2020
Same issue here. Adding a
.jsin the import inside a TypeScript file does allow to compile it with the TypeScript compiler and will output files with working ESM imports.However, when I add
.jsextensions on the imports, I can't get testing working. Tried with Mocha and Jest, but no luck so far: they complain the files with.jsextension don't exist, which is correct, those files don't exist since they actually have a.tsextension.I would love to see the TypeScript compiler add
.jsextenstions on imports when the output is esm/es2015.bobbyg603 commentedon Dec 27, 2020
Jos de Jong (@josdejong) you can get around this by using an
index.tsfile.In the index.ts file do the following:
export { MyClass } from 'src/my-class.js'In your test just import the file directly instead of via the index file:
import { MyClass } from 'src/my-class'46 remaining items
djfm commentedon Nov 4, 2022
gastonmorixe commentedon Nov 13, 2022
François-Marie de Jouvencel (@djfm) no, unbelievable
Nimmidev commentedon Nov 13, 2022
This has nothing to do with VSC and also works in every other editor with the typescript LSP. Completely unrelated to this issue.
build: explicit file extensions for imports
feat: initial commit (#2)
feat: initial commit (#2) (#4)
feat: initial commit (#2) (#4) (#5)
ci: release-please fix (#6)
ci: release-please fix (#8)
jmrossy commentedon Feb 3, 2023
2023 now, and the flicker of hope for this feature is still alive!
See #47436 (comment)
jogibear9988 commentedon Feb 3, 2023
Here a few pull requests or issues, where i need only file extensions (.js) so I could use them in browser:
adobe/css-tools#90
wokwi/wokwi-elements#149 (comment)
I don't know why an extra option wich I created in my pull request could not be added...
jogibear9988 commentedon Feb 3, 2023
I know use a js script to add the extension afterwards, see the pull I created here on how to do: wokwi/wokwi-elements#150
ernestostifano commentedon Feb 25, 2023
Just leaving my
+1here... can't believe this is still an issue.Would be as simple as to allow using
.tsextensions and then transform them into.js.This would make everyone happy: hundreds of people asking for it and TS maintainers because TS principles will not be affected this way (read this comment).
Hope TS maintainers will reconsider this soon.
(Continues here)
RyanCavanaugh commentedon Feb 27, 2023
Cross-posting this comment which explains that this is, very much intentionally, not something we are going to do.