Closed mattpocock closed 1 year ago
It does fail fairly fast if you set it true
today, albeit without a nice warning, since VMS is always dialect specific. (Unless you polyfill literally every file in src, I guess, but then why even use this module? :joy:)
In general, default exports are kind of a huge pita for hybrid builds. You pretty much must use a cjs polyfill in that case, or else you get the weird const blah = require('pkg').default
wart, and if you use export =
in the CJS polyfill, you can't export types along with it (and so these have to go in a global namespace).
For example:
The bigger hazard, though, is non-default exports, I think.
$ cat src/index.ts
import x = require("url");
export { x };
$ tsc -p .tshy/commonjs.json
src/index.ts:2:10 - error TS1286: ESM syntax is not allowed in a CommonJS module when 'verbatimModuleSyntax' is enabled.
2 export { x };
~
Found 1 error in src/index.ts:2
To be honest, I'm not sure how it's possible/reasonable to use verbatimModuleSyntax with a hybrid package. It ties the input code to the emit format in a way that is fundamentally inflexible, effectively turning "ts->commonjs" and "ts->esm" into two different source dialects.
So, the best solution seems to be: detect VMS early, and fail immediately if tshy.dialects.length > 1
.
@isaacs would you be open to supporting an opt-out of this behaviour for module authors who are (thoughtfully) avoiding default exports?
My understanding is that for such modules, verbatimModuleSyntax
results in a more well-defined authoring experience and wouldn't be problematic for the CJS / ESM interop nightmare.
@ggoodman Unfortunately, the syntax for importing and non-default exports are also different between CJS and ESM when VMS is enabled. verbatimModuleSyntax
does avoid the challenges of write-once and shipping to both esm and cjs, by making it 100% impossible to do that ("doc, it hurts when I do this" style).
If you're using verbatimModuleSyntax, then every build must be either CJS or ESM, and the code has to be aware of where it's going, because you can't use ESM-style syntax for a CJS build if you're using verbatimModuleSyntax, so tshy is irrelevant in that case.
My recommendation: If you are shipping one dialect, and find verbatimModuleSyntax style to be clearer and helpful for your program (personally, I think it is, but it's subjective style opinion of course), then do not use tshy, because it is not really offering you much. Just use tsc.
This is an interesting wrinkle. verbatimModuleSyntax enforces the correct usage of
export default
andexport =
in your code.But since tshy runs
tsc
in bothcjs
andesm
mode on your code, thenverbatimModuleSyntax
can never be resolved correctly. Either yourexport default
is incompatible withcjs
, orexport =
is incompatible withesm
.Interested in your thoughts - you could:
verbatimModuleSyntax
is set totrue
, with a nice warning.verbatimModuleSyntax
to false when emittingcjs
. And vice versa.