Skip to content
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

rewriteRelativeImportExtensions: tsc doesn't rewrite extensions in emitted declaration files #61037

Open
darksabrefr opened this issue Jan 24, 2025 · 4 comments

Comments

@darksabrefr
Copy link

🔎 Search Terms

"rewriteRelativeImportExtensions", "extensions", "declaration", ".d.ts"

🕗 Version & Regression Information

  • This is the behavior in every version I tried (even in the next 5.8.0), and I reviewed the FAQ for entries about "rewriteRelativeImportExtensions"

⏯ Playground Link

No response

💻 Code

In an index.ts file:

export * from './file.ts';

then build it with tsc and "rewriteRelativeImportExtensions": true & "declaration": true in the compilerOptions of your tsconfig.json

🙁 Actual behavior

Built files content:
In the JS file, index.js, the extension is rewritten to .js:

export * from './file.js';

In the declaration file, index.d.ts, the extension is not rewritten to .js:

export * from './file.ts';

🙂 Expected behavior

In the declaration file, the extension should be rewritten to .js too:

export * from './file.js';

Additional information about the issue

It occurs in the current TS 5.7.3 and in the next version (5.8.0-dev.20250123 at this time). Even if TS correctly interprets .d.ts files with .ts extensions in import/export, it's not the case of the IDE I use, PhpStorm. It can't provide a real code assistance with these declaration files.
In fact, I don't really know if it's a feature, a bug or an oversight in tsc, or if rewriteRelativeImportExtensions is just too new to be completely supported by all IDEs! Let me know!

@MartinJohns
Copy link
Contributor

MartinJohns commented Jan 24, 2025

This seems to be intentional, or at least not considered a bug: #59767 (comment)

@darksabrefr
Copy link
Author

Reading the Ryan Cavanaugh's comment and the rest of this thread let me think it's not really intentional but a form of "it's OK for TS, so there's no real problem with that". He only says what is clearly and intentionally not supported is the aliases resolving and rewriting, but it's not the problem here.
The fact is it breaks usages in some, maybe any, IDEs and probably in other tools, making this feature not totally usable in production right now. Maybe they will support it at some point, maybe not. I just think it's unfortunate in this case because if tsc is able to rewrite extensions in generated .js files, the gap to apply this to generated .d.ts files doesn't seem to be really high, while it ensures the best compatibility with existing tools in the eco-system.

I can't find any tests about this behavior in the linked PR, and the documentation doesn't mention it at all, it just says "output files", not "output files, excluding declaration files":

Rewrite .ts, .tsx, .mts, and .cts file extensions in relative import paths to their JavaScript equivalent in output files.

I really think generated .d.ts files were simply forgotten by this feature.

@RyanCavanaugh
Copy link
Member

The fact is it breaks usages in some, maybe any, IDEs and probably in other tools, making this feature not totally usable in production right now

Can you clarify what usages in particular? This isn't very concrete and there's no way for me to verify what you're referencing.

@darksabrefr
Copy link
Author

The usage problem that I encountered is precisely the one mentioned here : #59767 (comment). What this comment doesn't say, is it occurs in PhpStorm/WebStorm. I don't know for other IDEs or tools, I can only presume that the support is uneven, but at least Jetbrains IDEs fail to resolve relative imports in .d.ts files if the used extension is .ts, breaking the coding assistance on any exported thing in libraries where this appears. Typescript has no problem with that, as you stated yourself, it's perfectly valid for it. To be totally transparent, an issue in opened in Jetbrains Youtrack for more than a year, with no responses (see: https://youtrack.jetbrains.com/issue/WEB-64117/Ignore-file-extension-when-resolving-imports).

So what the problem behind that? It's really simple: finding public libraries with .d.ts having imports of *.ts is pretty uncommon at this time. In fact, I use, try and play with many typed libraries for a long time, and I've never spotted this Jetbrains issue before.
The first time I encountered it, is by experimenting the new rewriteRelativeImportExtensions tsc option in one of our internal library. I was evaluating the possibility to replace the tsx loader by the node native TS support, that requires to use source paths in imports rather than the traditional build destination paths required by TS (in fact, by the built ESM files as TS nearly ignores extensions). Currently, we use tsc to build our libraries, and we use tsx to comfortably launch units tests while developing, avoiding the need to build the library again and again, but also to run in place some TS scripts (some for development, some others distributed once built with tsc, some both). We clearly are in a situation where we run TS files in place and where we build a distributed ESM library on a single code base.

Since the introduction of the rewriteRelativeImportExtensions tsc option and my personal tests, I'm worried about the fact that these kind of .d.ts will be more and more common, in particular in public libraries published in npm repository, because this option will be used, and probably massively used, regardless of the doubts you raised for years about path rewriting (and to be really honest, I share these doubts) as there's few alternatives at this time to get a TS code base compatible with the more and more prominent "run TS in place" and building+distributing npm ESM modules.
That's why I said that rewriteRelativeImportExtensions is not reasonably usable in production right now: it may generate .d.ts files not totally compatible with the ecosystem (but perfectly valid in the TS point of view), at least not totally identical to those generated without this option + a traditional (with .js imports) ESM code base.

So Ryan, as you are one the deciders of the Typescript team, if tsc doesn't rewrite paths in .d.ts files, while it does rewrite the exact same ones in .js files, is it:

  • an oversight while implementing rewriteRelativeImportExtensions?
  • a bug?
  • a wanted behavior?
    Even if my opinion is the first choice, it's just an opinion, not a definitive response. And I need a response, not an opinion, to continue my evaluations 🙂

Thank you for your time!

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

No branches or pull requests

3 participants