Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot import declared enum #1253

Closed
GrabbenD opened this issue May 6, 2021 · 6 comments
Closed

Cannot import declared enum #1253

GrabbenD opened this issue May 6, 2021 · 6 comments

Comments

@GrabbenD
Copy link

GrabbenD commented May 6, 2021

Importing exported enums from a seperate file doesn't seem to work. You can still use the enum within the same file though. For example:

src/constants/index.ts

export declare enum MyEnum {
  valueOne,
  valueTwo
}

src/index.ts

console.log(MyEnum.valueOne);

Result:

 > src/index.ts:3:9: error: No matching export in "src/constants/index.ts" for import "MyEnum"
    3  import { MyEnum } from "src/constants";

Workaround?
Exporting the enum as a const works:

export const enum MyEnum {}
@evanw
Copy link
Owner

evanw commented May 6, 2021

In your example, the TypeScript compiler (i.e. running tsc) generates the following code:

  • src/constants/index.js

    "use strict";
    exports.__esModule = true;
  • src/index.js

    "use strict";
    exports.__esModule = true;
    var constants_1 = require("./constants");
    console.log(constants_1.MyEnum.valueOne);

So there is no enum to import, and the generated code will crash at run-time. What are you trying to do? What is the use case? Is there a use case for getting a run-time crash instead of a compile-time error?

Since esbuild doesn't have a type system, the export declare enum type annotation is the same as a comment (it's ignored). This is what is causing the error.

Files are compiled one-at-a-time so esbuild requires TypeScript's isolatedModules setting to be enabled. It is supposed to cause TypeScript to reject code that doesn't work when files are compiled independently. However, it's allowing export declare enum here which seems like it could be incorrect to me. They previously changed the TypeScript compiler to disallow export declare const enum: microsoft/TypeScript#28465. I wonder if it could make sense to have the TypeScript compiler consider your code an error as well.

@GrabbenD
Copy link
Author

GrabbenD commented May 7, 2021

Thanks fore the detailed answer @evanw!

Admittedly I might be using this wrong. The confusion comes from the fact that export declare enum MyEnum {} works in react-native and I'm able to import the Enum just fine in all submodules. My exact use case is that I'd like to keep track of valid values supported by a switch case. From my understanding the values inside a enum are converted to binary numbers and thus this should provide faster lookup times rather than iterating strings (don't quote me on this).

@evanw
Copy link
Owner

evanw commented May 7, 2021

Can you provide instructions for how to compile the code in your original post correctly? I will be able to understand this better if I can reproduce it myself.

I tried to reproduce this by setting up a React Native TypeScript project (https://reactnative.dev/docs/typescript), adding the code from your original post to the template, and running npm test. That doesn't work either:

> jest

 FAIL  __tests__/App-test.tsx
  ● Test suite failed to run

    TypeError: Cannot read property 'valueOne' of undefined

      1 | import { MyEnum } from './src/constants';
    > 2 | console.log(MyEnum.valueOne);
        |                    ^
      3 |
      4 | /**
      5 |  * Sample React Native App

      at Object.<anonymous> (App.tsx:2:20)
      at Object.<anonymous> (__tests__/App-test.tsx:7:1)

The contents of src/contents/index.ts was this:

export declare enum MyEnum {
  valueOne,
  valueTwo
}

So it seems like React Native doesn't support this either?

@GrabbenD
Copy link
Author

Thanks a lot for pointing this out @evanw! I created a Snack here https://snack.expo.io/Lg8tSfY3e to demonstrate this (refer to components/constants.ts) and you're completely right. However, I'm not sure yet why our react native typescript project is successfully parsing export const enum and export declare enum yet.

I believe the main takeaway of this is that ESBuild shouldn't parse export const enum 👍

@evanw
Copy link
Owner

evanw commented May 14, 2021

I believe the main takeaway of this is that ESBuild shouldn't parse export const enum 👍

I think export const enum should be fine. TypeScript just treats export const enum the same as export enum when isolatedModules is enabled. Since it works fine with TypeScript, it's fine if esbuild does that too.

I'm going to close this issue because it sounds like esbuild is doing the right thing here. The behavior is a little different than TypeScript in that the error happens at compile-time instead of run-time, but that seems better to me. I'd rather know about bundle linkage failures at compile-time in this case.

@evanw evanw closed this as completed May 14, 2021
okxiaoliang4 added a commit to okxiaoliang4/test-utils that referenced this issue Jul 2, 2022
connor4312 added a commit to microsoft/vscode-js-debug-companion that referenced this issue Jul 6, 2023
This breaks esbuild (evanw/esbuild#1253). We should probably move these to non-const in js-debug-browser.
@ko-devHong
Copy link

@evanw Problems occur when the code written in the library, not the code I wrote, is compiled.
ex) https://github.com/software-mansion/react-native-screens

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants
@evanw @ko-devHong @GrabbenD and others