denoland / dnt

Deno to npm package build tool.
MIT License
1.22k stars 37 forks source link

TextEncoder/TextDecoder not yet available #185

Open brickpop opened 2 years ago

brickpop commented 2 years ago

First of all, thank you for the great work behind DNT and Deno itself!

TextDecoder and TextEncoder cannot be used yet to compile to NPM modules. I know it is expected, just adding for reference.

Source:

const hexDecode = (s: string) => new TextEncoder().encode(s);

console.log(hexDecode("1234"));

Build output:

[dnt] Building project...
[dnt] Type checking...
src/mod.ts:9:38 - error TS2304: Cannot find name 'TextEncoder'.

9 const hexDecode = (s: string) => new TextEncoder().encode(s);
                                       ~~~~~~~~~~~

error: Uncaught (in promise) Error: Had 1 diagnostics.
        throw new Error(`Had ${diagnostics.length} diagnostics.`);
              ^
    at build (https://deno.land/x/dnt@0.27.0/mod.ts:299:15)

Thank you!

dsherret commented 2 years ago

Is this fixed if you add a @types/node dev dependency?

await build({
  // etc...
  package: {
    // etc...
    devDependencies: {
      "@types/node": "^16.11.37"
    }
  }
});

Otherwise, if you're targetting the browser, then enable DOM types: https://github.com/denoland/dnt#dom-types

brickpop commented 2 years ago

The devDependency is there indeed:

image


And npm install is being run:

image

dsherret commented 2 years ago

So the main issue here is that @types/node doesn't have TextEncoder or TextDecoder as a global (I did not know this until just now). I looked into fixing this in DefinitelyTyped, but I'm not sure how the typings would look like without conflicting with existing lib.dom.ts globals (if present). There's some discussion here on fixing this: https://github.com/microsoft/TypeScript/issues/31535

Browser Workaround

Enable DOM types, which you should be doing anyway if you're targeting the browser: https://github.com/denoland/dnt#dom-types

Node Workaround

If you're targeting for Node, add a custom shim that shims TextEncoder or TextDecoder to use util:

await build({
  // etc...
  shims: {
    custom: [{
      globalNames: ["TextEncoder", "TextDecoder"],
      module: "util",
    }]
  },
});

I added a test for this here: https://github.com/denoland/dnt/pull/192

brickpop commented 2 years ago

Thank you @dsherret, the change made the build pass! (yet a different issue popped up)

Should the readme be updated or some warning be displayed as a workaround?

sgwilym commented 2 years ago

If anyone needs an "isomorphic" TextEncoder/TextDecoder shim that works in both Node and the browser (where it will just use the built-in version):

await build({
  // etc...
  shims: {
    custom: [{
      package: {
        name: "textencoder-ponyfill",
          version: "1.0.2",
        },
        globalNames: ["TextEncoder", "TextDecoder"],
      },
    ]
  },
});