invariant
invariant copied to clipboard
Invariant can't be imported in TypeScript under jest vs metro-bundler/packager (in react-native)
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.
@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.
@maciejw Yes. I have both babel and webpack as I'm using ReactXP to target both web & react-native.
I have been able to work around this in our project by porting the code to TypeScript. Not sure if anybody would want that.
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 :)
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 viaimport invariant from 'invariant';
- Otherwise you must use the
import invariant = require('invariant');
syntax.
I had to use allowSyntheticDefaultImports: true
in my config for import invariant from 'invariant'
to work (with TS version 2.7.2
).