dataarts / dat.gui

Lightweight controller library for JavaScript.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Difference in export style between build/dat.gui.js and build/dat.gui.module.js makes using TypeScript declarations harder

efokschaner opened this issue · comments

Hello there, I found something that "could have been better" when using this library in TypeScript and wanted to let you know in case there was anything that could be improved on dat.gui's end.

As you may already know, there are type declarations provided for dat.gui in this repo: https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/dat.gui
If you've never heard of DefinitelyTyped check out the readme of the repo.

Recently, I started using dat.gui in a new webpack (4) project and I was not able to import dat.gui correctly while simultaneously satisfying the declared interface in the DefinitelyTyped repo. The DT types assume I'm importing via import * as dat from 'dat.gui', but if i do that, the emitted JS ends up with the object dat having a default property which contains the actual module. Whereas if I import dat from 'dat.gui' the emitted JS is correct and I can reference dat.GUI etc, but now the TypeScript compiler tells me there's "no default export" from the dat.gui module so my code must be wrong.

In https://github.com/dataarts/dat.gui/blob/master/src/dat/index.js#L31 there's a default export.
In https://github.com/dataarts/dat.gui/blob/master/build/dat.gui.js there appears to be no default export.
And in https://github.com/dataarts/dat.gui/blob/master/build/dat.gui.module.js#L2513 there's a default export again.

Originally, I tried to fix this in DefinitelyTyped, please see this PR for some context DefinitelyTyped/DefinitelyTyped#25188

Basically the conclusion there was that the typings should match the way they are in build/dat.gui.js and that I can enable a typescript compiler option called allowSyntheticDefaultImports in order to get TypeScript to allow this discrepancy.

I hope you would agree that it should not be necessary to enable obscure compiler options globally just to use dat.gui plus webpack plus typescript. So I wanted to reach out and see if there's anything dat.gui could do to solve this issue.

Is there anything that would seem to solve it? Such as removing the discrepancy between the two built files perhaps? I don't know enough about JS modules to know whether that's reasonable or not.

As mentioned I'd actually used dat.gui and those DefinitelyTyped types without problems in the past, and I suspect that this change might have introduced the issue:
1cf95b4#diff-b9cfc7f2cdf78a7f4b91a753d10865a2R6
I think when the package.json had a "module" field added, webpack may have started bundling it instead and that's what's going on here. Not saying that should be reverted, just trying to add as much as I know about the issue.

I don't regularly use TypeScript or Webpack, so suggestions here would be welcome. We only recently fixed issues where es6 modules were not available (#132), webpack did not work (#142), or CommonJS users had to do var dat = require('dat.gui').default so I would like to avoid re-introducing those issues of course. :)

Since build/dat.gui.js is a UMD module, I'm not sure what it would mean for it to have a default export... does DefinitelyTyped understand that a package may provide both UMD and ES6 modules? Is it better to just avoid default exports entirely?

Thanks for the response. Hmmm, sounds pretty tricky.

The typings repository doesn't distinguish different module forms of the same library, which is why I was proposing just describing them both in the one file in my DT PR, which we decided not to do in the end.
However it smells odd to me for the flavour of module to actually make an observable difference to the exported interface which is probably why there's no mechanism or convention for dealing with that in the typings repository.

Perhaps avoiding default export entirely might do it. But that might not be backward compatible for everyone importing the default? Perhaps having both? Export everything in dat individually as well as combined under the default? I can't speak with any authority on this... Perhaps @weswigham (who was pretty knowledgeable on my DT pr) could suggest a solution? Is there anything dat.gui could do better to avoid needing the allowSyntheticDefaultImports TSC option?

allowSyntheticDefaultImports exists precisely to allow this. It's is the correct flag to use. Webpack uses an alternative entrypoint that creates defaults for export assigned things, thus using the flag when you're using webpack is usually appropriate. There's nothing wrong with using the flag if your build pipeline is setup to work that way.

It's great that typescript has this flag and that it solves this problem. I just wonder if there's anything that can be done so that the next person using webpack (or perhaps any "module" aware bundler) with dat.gui and typescript doesn't need to go through the confusion that I went through. There's not another module I've encountered this with when using webpack. Is this some well known thing that when using DT with webpack you should expect to enable allowSyntheticDefaultImports? Do you have any thoughts on the ideas suggested in this issue so far?

I just wonder if there's anything that can be done so that the next person using webpack (or perhaps any "module" aware bundler) with dat.gui and typescript doesn't need to go through the confusion that I went through.

The default mode of operation for the compiler is for node-style cjs. If you're tooling or your environment is different you'll need to configure it - that's just how it is; we don't plan on changing the defaults in the near future.

Thanks Wes. Does that imply there's definitely no way that dat.gui's es6 module build could be "out of the box" compatible with the type declarations, or vice versa?

The type definitions themselves are already out of the box compatible with all the compilers' modes of operation. It is just a matter of compiler users deciding if they need to configure it to match their runtime behavior.

Thanks all!