LeDDGroup / typescript-transform-paths

Transforms module resolution paths using TypeScript path mapping and/or custom paths
MIT License
465 stars 22 forks source link

[Bug] Issues with Type Elision #184

Closed nonara closed 4 months ago

nonara commented 4 months ago

NOTE: This has been fixed in v3.4.7

Current Issues

TypeScript introduced a few new features, such as allowing the type keyword on individual import/export specifiers. (ie. import { type SomeType, nonType } from './a')

There was also a new compiler option added, verbatimModuleSyntax, which came into play.

Additionally, there seems to have been see some new logic added to elision process involving the compiler option importsNotUsedAsValues.

As a result, the current release can fail in a few cases which relates to these new features.

Background

Original Issue

Some time back, we ran into an issue with the TypeScript Compiler API which affected what is called "elision".

TypeScript elides (removes) import / export declarations either entirely or in part (removing individual specifiers) based on a number of factors. One such factor includes the "type-only" status of a declaration or import/export specifier. This becomes especially important during the emit phase for JavaScript files, as we want to ensure that there are no types emitted there.

It was discovered that elision will be blocked if any update is made on the import / export declaration Node.

If elision is blocked, it can have a number of unwanted side-effects. The most severe is the potential for references to types being emitted in the JS files (within import / export), which will break the output code.

Unfortunately, in cases where we need to update the module specifier for a path alias (ie. './path/to/file'), this would trigger blocking.

This issue was filed as a new issue on the TypeScript repo:

Note: This issue has recently been addressed by the TS team! More detail below

Prior Solutions

Because the elision methods within the compiler were not exposed, we could not directly feed into the TS compiler. Several attempts were made for workarounds, but they caused more edge cases.

Eventually, we ended up (mostly) replicating the compiler's elision code locally.

The ultimate trade-off to this approach is that it requires us to stay up to date with changes to that entire section of the compiler.

🎉 Future Update

The upcoming release of TypeScript has loosened elision blocking so that we will be able to update the module specifier without triggering a block.

(Major thanks to Ron Buckton and the team!)

This will allow us to no longer rely on our custom elision logic and will make it much easier to stay in sync with TS changes.

Previous related issues