ethereumjs / ethereumjs-util

Project is in active development and has been moved to the EthereumJS monorepo.
https://github.com/ethereumjs/ethereumjs-monorepo
Mozilla Public License 2.0
604 stars 274 forks source link

Fix the types of the BN and RLP re-exports #270

Closed alcuadrado closed 4 years ago

alcuadrado commented 4 years ago

This PR fixes #267.

Here's an explanation of what I think was wrong, how I fixed, and how it can be simplified in the future.

  1. BN and RLP are distributed as CJS modules, and use the module.exports = pattern. This is ok in CJS, but doesn't make sense in ESM. module.exports is not the same as export default.

  2. TS has a special syntax to do that, export = obj.

  3. BN and RLP typings use that syntax.

  4. To import modules using that syntax, you have to use import A = require('A') in ts.

  5. This module was using import * as A from 'A' instead, which means something like "import the module namespace" in ESM. Not that module namespace is not a class in ESM, so ts gets confused if you try to initialize it.

  6. This worked anyway, as we are just reexporting it, so no error was triggered.

  7. When a TS project tries to use it, ts complains about this error that went unnoticed here.

  8. This make this CSJ/ESM compatibility mess easier, TS introduced the esModuleInterop flag, which let you use import A as 'A' to import CSJ modules. This breaks the ESM semantics a bit, but it's a great trade off.

  9. As I wrote in a TODO, we are gonna enable that flag in a future version of the ts config package, so this change can be simplified in the future.

coveralls commented 4 years ago

Coverage Status

Coverage remained the same at 99.711% when pulling fa5801f6721025c811f3280f4163f38d597df1dc on fix-ts-reexports into ba3e344b5133a6d110bbc8cc04b78c225521f667 on master.

ryanio commented 4 years ago

thanks for the explanation :)

As I wrote in a TODO, we are gonna enable that flag in a future version of the ts config package, so this change can be simplified in the future.

could we just add esModuleInterop to this repo's tsconfig and keep the export the same? that would skip the need for adding a future TODO. or is it better to use this import/require syntax

alcuadrado commented 4 years ago

I tried your suggestion. It didn't work. I'm not sure why tbh