Parcel: .ts files importing from npm module with provided .js and .ts sources do not resolve const enums

Created on 15 Oct 2019  路  9Comments  路  Source: parcel-bundler/parcel

馃悰 bug report

Given is the following example.ts file:

import {MyEnum} from 'my-module';

var example = MyEnum.Something;

And given is an npm module with the following files:

  • my-module.d.ts
  • my-module.d.ts.map
  • my-module.js
  • my-module.js.map
  • src/my-module.ts

my-module.ts:

export const enum MyEnum { Something = 'constantString' };

The module itself is working properly.

馃帥 Configuration (.babelrc, package.json, cli command)

Everything default. tsconfig.json has preserveConstEnums: false (intentionally).

馃 Expected Behavior

In the bundled code, the line from the example.ts should look like:

var example = "constantString";

馃槸 Current Behavior

Currently however, it bundles it to:

var example = MyEnum.Something;

Whereas MyEnum.Something must be resolved to the constant string behind it. Obviously, MyEnum is not existing at run time and thus gives me "undefined" errors.

馃拋 Possible Solution

I have tested the following:
First running tsc and then using parcel build on the outputted files. It worked correctly, as tsc does inline the constant enums correctly. tsc seems to process the provided .d.ts correct to use the constant strings given.

Without knowing on what exact way Parcel currently compiles TypeScript files, I would suggest tsc itself must run over the entire project, and then Parcel performs it's other processing.

馃敠 Context

I created an own private npm module exporting .js but also the original .ts files, to provide maximum compatibility for those not using TypeScript.
However, now I see myself unable to use const enums from my own bundle in my TypeScript files.
The only solution would be to use preserveConstEnums, which however is only a work around and no desired fix. Alternatively I could use a const variable with a set of given strings. But that also is only a work around.

馃實 Your Environment

| Software | Version(s) |
| ---------------- | ---------- |
| Parcel | 1.12.4
| TypeScript | 3.6.4
| Node | 10.16.0
| npm/Yarn | 6.9.0
| Operating System | Windows 10 64bit

Question TypeScript

All 9 comments

Related: https://github.com/parcel-bundler/parcel/issues/3624 (const enums aren't supported).

thus gives me "undefined" errors.

not sure if we can do something about that...

Is there potentially any downside to manually first executing tsc and then letting Parcel run over the outputted JS files? Other than possibly having HMR not usable?

I don't think so (but be sure that tsc emits modules with ES6 imports (not CommonJS) and also set the target to the newest value to leave the JS feature transpilation to Parcel)

A work-around for now:

I use tsc first and then let Parcel handle those files. Making sure TypeScript does it's thing properly.
A build script would look like this:

"build": "tsc && parcel build index.html"

And to keep Parcel's Hot Module Replacement working, the following watch-script can be used:

"watch": "tsc && npm-run-all -p watch:*",
"watch:ts": "tsc -w",
"watch:js": "parcel index.html",

It requires npm-run-all to be installed.

Initially the watching takes longer because tsc first must be executed to make sure Parcel does not run on work-in-progress files.

So far I have not seen any downsides to this approach, other than being an undesired work-around. I will keep this issue updated if I encounter anything problematic. Also, I will keep it open as the issue itself is not fixed by it, unless a Dev decides otherwise.

This is how I got it working in the end. Bit clunky but works for now.

Bump (to remove stale marking), unexpected differences between standard TypeScript compilation and Parcel TypeScript compilation should be considered an issue and left open until fixed (even if it's a downstream dependency that has to apply the fix).

Parcel 2's approach is to use isolatedModules with the tsc compiler and Babel doesn't support this at all.

This article sums up the reasons: https://ncjamieson.com/dont-export-const-enums/

standard TypeScript compilation

So isolatedModules is a non-standard tsc config?

At the least, it can confuse people why tsc generates working code out of the box and parcel doesn't...maybe a blurb on https://parceljs.org/typeScript.html (or the parcel 2 equivalent) is enough saying const enums aren't supported (or that isolatedModules should be set to true in tsconfig.json or something).

It's already on the todo list for the new typescript docs: https://parcel2-docs.now.sh/recipes/typescript/

Was this page helpful?
0 / 5 - 0 ratings