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

Invariant can't be imported in TypeScript under jest vs metro-bundler/packager (in react-native) #32

Open
fbartho opened this issue Jan 25, 2018 · 6 comments

Comments

@fbartho
Copy link

fbartho commented Jan 25, 2018

Using invariant imported with the following two patterns fails opposite depending on how we run the build (either as unit-tests under jest, or as a react-native view on android).

import * as invariant from "invariant";
import invariant from "invariant";

Swapping the import from one to the other enables/disables using invariant in the opposite target.

@maciejw
Copy link

maciejw commented Feb 5, 2018

@fbartho do you have babel in your build config? I have no problems with jest, because I have ts transpiler only, when I use it with webpack ts and babel, then I have an error invariant is not a function.

@fbartho
Copy link
Author

fbartho commented Feb 5, 2018

@maciejw Yes. I have both babel and webpack as I'm using ReactXP to target both web & react-native.

@fbartho
Copy link
Author

fbartho commented Feb 5, 2018

I have been able to work around this in our project by porting the code to TypeScript. Not sure if anybody would want that.

@maciejw
Copy link

maciejw commented Feb 6, 2018

ok I have some info regarding subject.
https://www.typescriptlang.org/docs/handbook/declaration-files/library-structures.html
thats the reason I think

The Impact of ES6 on Module Call Signatures
Many popular libraries, such as Express, expose themselves as a callable function when imported. For example, the typical Express usage looks like this:

import exp = require("express");
var app = exp();

In ES6 module loaders, the top-level object (here imported as exp) can only have properties; the top-level module object is never callable. The most common solution here is to define a default export for a callable/constructable object; some module loader shims will automatically detect this situation and replace the top-level object with the default export.

this is how invariant is exported

module.exports = invariant;

so bundler should shim it, this could be configuration issue,
or invariant library could add "module" next to "main" in package.json and export invariant function from another file correctly as es6 modules require it, default or named way, to resolve this

as a workaround require can be used, and then reexport using es6 syntax.

or we can PR this if this last solution is OK :)

@bradleyayers
Copy link

Prior to TypeScript 2.7, CommonJS modules that exported a function as the module (i.e. module.exports = function () { … }) could not be imported as an ES module. This meant that it was not possible to import this type of modules ("callable CommonJS module") using ES module import syntax (e.g. import foo from 'foo' or import * as foo from 'foo').

This changed in TypeScript 2.7 with the introduction of --esModuleInterop that enables TypeScript modules to import "callable CommonJS modules" using ES module default import syntax.

This boils down to:

  • If you're using TS 2.7 or newer with --esModuleInterop this module can be imported via import invariant from 'invariant';
  • Otherwise you must use the import invariant = require('invariant'); syntax.

@andrezsanchez
Copy link

andrezsanchez commented Mar 31, 2018

I had to use allowSyntheticDefaultImports: true in my config for import invariant from 'invariant' to work (with TS version 2.7.2).

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