question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Use of enums is transpiled in a different way than with tsc

See original GitHub issue

For some reason TypeScript enum values are transpiled differently with ts-node than with tsc. This can lead to runtime errors if the used enum doesn’t exist at runtime.

Here’s an example: the current typings for big.js define an enum that doesn’t actually exist in the JS library:

// node_modules/@types/big.js/index.d.ts
export const enum Comparison {
    GT = 1,
    EQ = 0,
    LT = -1,
}

This enum doesn’t exist at runtime:

console.info(require('big.js').Comparison)
// undefined

Now, let’s say we have this TS code:

import {Comparison} from 'big.js'

Comparison.LT.toString()

tsc transpiles it to this (using a sane tsconfig.json with ES2017 target):

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
-1 /* LT */.toString();

Note that there’s no require calls anywhere and the enum value -1 is inlined with a comment included. Running the generated JS file with node doesn’t throw any exceptions.

Now, running the same TS file with ts-node gives me this:

/home/joonas/enum-bug/main.ts:3
Comparison.LT.toString()
           ^
TypeError: Cannot read property 'LT' of undefined
    at Object.<anonymous> (/home/joonas/enum-bug/main.ts:3:12)
    at Module._compile (module.js:643:30)
    at Module.m._compile (/home/joonas/enum-bug/node_modules/ts-node/src/index.ts:423:6)
    at Module._extensions..js (module.js:654:10)
    at Object.require.extensions.(anonymous function) [as .ts] (/home/joonas/enum-bug/node_modules/ts-node/src/index.ts:426:4)
    at Module.load (module.js:556:32)
    at tryModuleLoad (module.js:499:12)
    at Function.Module._load (module.js:491:3)
    at Function.Module.runMain (module.js:684:10)
    at Object.<anonymous> (/home/joonas/enum-bug/node_modules/ts-node/src/_bin.ts:177:12)

After adding some logging to ts-node inside my node_modules, I can see that this is the transpiled output:

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const big_js_1 = require("big.js");
big_js_1.Comparison.LT.toString();

Note the require call and how the enum value is not inlined but accessed at runtime.

Any ideas? This might of course be a misconfiguration in my part, a TS compiler bug, or a problem with the compiler API.

$ node --version
v8.9.4

Library versions:

  "dependencies": {
    "@types/big.js": "4.0.2",
    "big.js": "5.0.3",
    "ts-node": "4.1.0",
    "typescript": "2.6.2"
  }

Issue Analytics

  • State:closed
  • Created 6 years ago
  • Reactions:9
  • Comments:13 (6 by maintainers)

github_iconTop GitHub Comments

6reactions
svkurowskicommented, Mar 7, 2018

Hello, please re-open this issue and remove the invalid label as ts-node is behaving differently than tsc and node for completely valid TypeScript code. Here is a minimal example to reproduce:

MyEnum.ts:

const enum MyEnum {
    A = "A",
    B = "B",
}
export default MyEnum;

index.ts:

import MyEnum from "./MyEnum";
console.log(MyEnum.A)

Expected behavior as evidenced by tsc/node:

$ node_modules/.bin/tsc index.ts MyEnum.ts
$ node index.js
A

Actual behavior of ts-node:

$ node_modules/.bin/ts-node index.ts

index.ts:2
console.log(MyEnum.A)
                   ^
TypeError: Cannot read property 'A' of undefined
    at Object.<anonymous> (index.ts:3:20)
    at Module._compile (module.js:660:30)
    at Module.m._compile (node_modules/ts-node/src/index.ts:400:23)
    at Module._extensions..js (module.js:671:10)
    at Object.require.extensions.(anonymous function) [as .ts] (node_modules/ts-node/src/index.ts:403:12)
    at Module.load (module.js:573:32)
    at tryModuleLoad (module.js:513:12)
    at Function.Module._load (module.js:505:3)
    at Function.Module.runMain (module.js:701:10)
    at Object.<anonymous> (node_modules/ts-node/src/bin.ts:141:12)

Yes, it works correctly with the TS_NODE_TYPE_CHECK environment variable set to Y but this issue should still be fixed.

1reaction
electricessencecommented, Mar 28, 2018

Oddly… I ran my tests against pure typescript as well (no JS) and const enums still did not propagate correctly. I had to set “preserveConstEnums” to true.

Read more comments on GitHub >

github_iconTop Results From Across the Web

typescript - Enum type not defined at runtime - Stack Overflow
The compiler lets me use it in other ts files, and appears to be happy. However, at runtime I get the error "MyEnum...
Read more >
Handbook - Enums - TypeScript
Enums allow a developer to define a set of named constants. Using enums can make it easier to document intent, or create a...
Read more >
Choosing between Babel and TypeScript - Tinkerer
A const enum is an enum that TypeScript compiles away to nothing. Let's take a look at how to use it, and what...
Read more >
TypeScript string enums, and when and how to use them
The enums keyword offers a way for us to define a finite set of values — usually as named constants in a strongly...
Read more >
TypeScript Features to Avoid - Hacker News
I haven't used Typescript, but I imagine this style was used so enums could gain new values later in the code without having...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found