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.

`esModuleInterop: true` cause runtime error

See original GitHub issue

Hi there, problems happened when I toggled esModuleInterop flag for my project, I have to because one library it depends enabled this flag.

TypeScript Version: 2.7+

Search Terms: esModuleInterop allowSyntheticDefaultImports

Code

import * as apmStar from 'elastic-apm-node'
import SentryDefault from '@sentry/node'

apmStar.start // undefined
SentryDefault // undefined

Explains:

  • for @sentry/node it is an es module, so esModuleInterop has no effects on it, but with allowSyntheticDefaultImports you can import its default, which property it does not export, so you got an undefined error at runtime
  • for elastic-apm-node, it is a commonjs module, and it exports an instance, start is a prototype method of it, so it is lost after __importStar.

But these problems are not informed in the document, guess we could discourage enabling it for library projects? And I wonder if we could improve type checking for these situations, for example:

  • for apmStar, it is imported as esmodule namespace, so an type error could be thrown when accessing .start method on it.
  • for SentryDefault, it is a esmodule, allowSyntheticDefaultImports could be disabled for it

Expected behavior: Error emitted at compiling time Actual behavior: Compiled successfully, but got an error at runtime.

Playground Link: https://repl.it/@themez1/esModuleInteropTest

Related Issues: https://github.com/microsoft/TypeScript/issues/28009 https://github.com/microsoft/TypeScript/issues/33954 https://github.com/microsoft/TypeScript/issues/36026

Issue Analytics

  • State:open
  • Created 3 years ago
  • Reactions:1
  • Comments:13 (5 by maintainers)

github_iconTop GitHub Comments

4reactions
octogonzcommented, Mar 2, 2021

We encountered a similar issue in https://github.com/microsoft/rushstack/issues/2526 . The repro is very easy:

  1. Create a TypeScript project that imports the colors package (version 1.2.5 in our case)
  2. Enable esModuleInterop=true in tsconfig.json
  3. Observe that this is the correct way to import the library:
    // Emitted as:  const colors_1 = __importDefault(require("colors"));
    import colors from 'colors'; 
    
    console.log('Some ' + colors.red('colored text')); // works great
    
  4. Now try this way:
    // Emitted as:   const colors = __importStar(require("colors"));
    import * as colors from "colors";  // compiles without any error message 
    
    // Fails at runtime with "TypeError: colors.red is not a function"
    console.log('Some ' + colors.red('colored text'));
    

@RyanCavanaugh in our case, setting allowSyntheticDefaultImports=false reports an error for the correct import form. So that doesn’t seem to be a solution.

Setting esModuleInterop=true causes the compiler to silently accept code that will fail at runtime. These bugs may lurk in the code base for a long time until someone hits that code path (and bothers to report it). Maybe something is wrong with the typings for the colors package, but we’ve also encountered this with various other popular Node.js packages.

What’s the right way to prevent these mistakes? We never had these problems with esModuleInterop=false.

1reaction
weswighamcommented, Mar 17, 2022

It’s definitely a guaranteed indicator that the file is a cjs-format module that’s masquerading as an es module and has no default presented by ts/babel’s import helpers.

You shouldn’t put it in the declarations for actually-esm format modules, however, since those don’t use any import helpers 😛

Read more comments on GitHub >

github_iconTop Results From Across the Web

TSConfig Option: esModuleInterop - TypeScript
This mis-match causes these two issues: the ES6 modules spec states that a namespace import ( import * as x ) can only...
Read more >
Understanding esModuleInterop in tsconfig file - Stack Overflow
It works and it's perfectly valid with es6 modules spec, because moment is not namespace from star import, it's default import.
Read more >
TypeScript intellisense in VS2019 falsely showing error "... can ...
I have both “esModuleInterop” and “allowSyntheticDefaultImports” set to true ... The tsx files still compile correctly and I do not get any runtime...
Read more >
Configuration | Manual - Deno
checkJs, false, If true causes TypeScript to type check JavaScript ... This is the "default" library used when checking Deno main runtime scripts....
Read more >
TSConfig Reference - TypeScript
When imported into a TypeScript file will raise an error: ... These limitations can cause runtime problems for some TypeScript ... Flag, esModuleInterop....
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