Skip to content

fix(typescript): avoid resolving definition files with arbitrary extensions#1949

Open
ychavoya wants to merge 3 commits intorollup:masterfrom
ychavoya:arbitrary-extensions
Open

fix(typescript): avoid resolving definition files with arbitrary extensions#1949
ychavoya wants to merge 3 commits intorollup:masterfrom
ychavoya:arbitrary-extensions

Conversation

@ychavoya
Copy link

@ychavoya ychavoya commented Nov 28, 2025

Rollup Plugin Name: typescript

This PR contains:

  • bugfix
  • feature
  • refactor
  • documentation
  • other

Are tests included?

  • yes (bugfixes and features will not be merged without tests)
  • no

Breaking Changes?

  • yes (breaking changes will not be merged unless absolutely necessary)
  • no

If yes, then include "BREAKING CHANGES:" in the first commit message body, followed by a description of what is breaking.

List any relevant issue numbers: resolves #1858

Description

This PR updates the regular expression used to detect declaration files (*.d.ts) to include declaration files for arbitrary extensions, such as the ones allowed with the allowArbitraryExtensions compiler option (*.d.*.ts). By including these in the regex, they are not resolved and therefore prevent the error displayed in #1858.

Also, in order to add a test for this behavior, the typescript version in the dev dependencies was upgraded to v5 and therefore some other pieces of code had to be changed.

@ychavoya ychavoya requested a review from shellscape as a code owner November 28, 2025 22:33
*/
export function isDeclarationOutputFile(name: string): boolean {
return /\.d\.[cm]?ts$/.test(name);
return /\.d(\..+)?\.[cm]?ts$/.test(name);
Copy link
Member

@emersion emersion Feb 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was wondering whether an arbitrary string is allowed between .d. and .ts, or if only a restricted set of characters are allowed. It turns out any arbitrary string is allowed here:

https://github.com/microsoft/TypeScript/blob/01c23d68b1113a4b71acb8484f1bf78a98307933/src/compiler/parser.ts#L10568

tl;dr this regexp sounds correct to me.

t.is(warnings.length, 1);
t.is(warnings[0].code, 'UNRESOLVED_IMPORT');
t.is(warnings.length, 2);
t.is(warnings[0].pluginCode, 'TS5110');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is this warning? Is it about the module value not being aligned with the moduleResolution value?

Shouldn't we resolve it instead?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Resolved! I was not sure if I should update this to include the warning, or this other statement https://github.com/rollup/plugins/pull/1949/changes#diff-9b47757e1347eae5ab5cefedce0669826e925f9b073a02815b9507b782f2211bL1540 since changing the module changes how the code is output in the test.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What the test cares about is the unresolved import, so I'd say it's better if we avoid any other unnecessary noise :P

}

const configCache = new Map() as typescript.ESMap<string, ExtendedConfigCacheEntry>;
const configCache = new Map() as Map<string, ExtendedConfigCacheEntry>;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: could we avoid the cast here by using new Map<string, ExtendedConfigCacheEntry>() instead?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, I missed that when changing it

Copy link
Member

@emersion emersion left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good apart from this minor warning-related comment!

@emersion
Copy link
Member

emersion commented Feb 5, 2026

These new changes look good! Can you squash them into the commits that introduced what they're fixing?

@ychavoya ychavoya force-pushed the arbitrary-extensions branch from c69a081 to 54649a3 Compare February 5, 2026 15:50
@ychavoya
Copy link
Author

ychavoya commented Feb 5, 2026

Done, I squashed the changes into the typescript upgrade, so now there are only the 3 commits I initially added. Let me know if you want them combined as well

Copy link
Member

@emersion emersion left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@emersion
Copy link
Member

emersion commented Feb 5, 2026

@shellscape, would you mind having a look?

@shellscape
Copy link
Collaborator

@emersion I would advise not adding an approving review to PRs in repos which you do not maintain.

@CharlieHelps please do a thorough review of this PR to determine if it's ready to merge. Look at the diff, reviews, comments, and referenced issues/docs/links to build a complete understanding. Then respond with a comment that includes a list of MUST fix items that must be fixed before the the PR is merged, and a list of IMPROVEMENTS that shouldn't block the merge but may be quick improvements or things that could be addressed in a follow up PR. The MUST fix items should explain exactly what's wrong and what needs to change to resolve the problem. Both should be numbered lists and the IMPROVEMENTS list should continue counting up from the MUST list. It's OK if there are no IMPROVEMENTS or MUST fix items, you can just omit the lists.

@charliecreates
Copy link
Contributor

Thanks for the PR — the .d.<ext>.ts handling matches TypeScript’s allowArbitraryExtensions behavior.

MUST fix

  1. Fix failing Linux CI (Validate Monorepo). The PR is currently red (e.g. Node v20 job): https://github.com/rollup/plugins/actions/runs/21718266321/job/63704024881.

    Locally, pnpm --filter "...[origin/master]" ci:coverage fails because the AVA runner times out / never exits (eventually OOM). On this branch it looks like the plugin is leaving a large number of live FSWatcher handles behind after a normal rollup() build (even without Rollup watch mode), which keeps the process alive.

    Change needed: ensure the TS watch program / file watchers are not left running for non-watch builds (e.g. don’t create a watch program when this.meta.watchMode is false, and/or dispose/close the program in a hook that runs during bundle.generate() such as generateBundle/buildEnd, since the tests don’t call bundle.close()).

  2. Track down the TS1110: Type expected diagnostic shown in the failing run (RollupError: @rollup/plugin-typescript TS1110: Type expected.). Please identify which file triggers it and adjust module resolution/arbitrary-extension handling so TS consumes the *.d.<ext>.ts declaration (and doesn’t try to parse the arbitrary extension source itself).

IMPROVEMENTS
3. Consider addressing the open TS5110 warning discussion by tweaking the fixture/tsconfig to avoid emitting the warning (rather than asserting on it), so the test output stays clean: #1949 (comment).
4. Small typing cleanup from the review thread: prefer new Map<string, ExtendedConfigCacheEntry>() over casting, if you touch that area again: #1949 (comment).
5. Tiny TS nit in the new fixture: use number instead of Number in module.d.custom.ts.
6. The new assertion that checks bundle.cache.modules is a bit indirect; consider also asserting the build succeeds without warnings/errors for that import to keep the test resilient.

@charliecreates charliecreates bot mentioned this pull request Feb 16, 2026
@emersion

This comment was marked as off-topic.

@shellscape

This comment was marked as off-topic.

@emersion

This comment was marked as off-topic.

@shellscape

This comment was marked as off-topic.

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

Successfully merging this pull request may close these issues.

@rollup/plugin-typescript seems not recognizing .d.[ext].ts style definition files?

3 participants