Description
In TypeScript 3.9, we started preserving export *
for type-only modules. While this keeps our behavior more predictable long-term, this caused bundle-size regressions for teams combining Webpack and TypeScript (webpack/webpack#10889).
My understanding of the situation is that tools like Webpack use a similar disambiguation strategy as that of TypeScript to figure out whether a file is a module. Given that, when Webpack resolved to an empty file, it would bail out of certain optimizations thinking it was a global script file. In reality, all users using ts-loader's transpileModule
mode were hitting this as well - it just turned out that the new behavior uncovered this behavior in a very large codebase.
We also discovered that we were not emitting "use strict"
prologue directives even under alwaysStrict
because we assumed that the output would be a module.
I also just discovered that import type { foo } from "bar"
doesn't force an export {}
in a module that does have values in it. That seems bad because this goes beyond special-casing for empty modules.
Here's the outcomes I could imagine:
- TypeScript always emits an
export {}
. Is this really useful if the fix is already in-flight for Webpack? - TypeScript always emits an
export {}
underalwaysStrict
when the output is empty (but then why does this matter?) - TypeScript keeps the current behavior.
Personally, my gut was to always emit the export {}
; then I swung into thinking that emitting export {}
on empty modules would be a weird vestigial behavior for empty modules. But then I realized that TypeScript doesn't emit any sort of module marker even when using import type
, so I'm back to thinking we should always emit export {}
.