49

With ES2015 syntax, we have the new import syntax, and I've been trying to figure out how to import everything exported from one file into another, without having it wrapped in an object, ie. available as if they were defined in the same file.

So, essentially, this:

// constants.js

const MYAPP_BAR = 'bar'
const MYAPP_FOO = 'foo'
// reducers.js

import * from './constants'

console.log(MYAPP_FOO)

This does not work, at least according to my Babel/Webpack setup, this syntax is not valid.

Alternatives

This works (but is long and annoying if you need more than a couple of things imported):

// reducers.js

import { MYAPP_BAR, MYAPP_FOO } from './constants'

console.log(MYAPP_FOO)

As does this (but it wraps the consts in an object):

// reducers.js

import * as consts from './constants'

console.log(consts.MYAPP_FOO)

Is there a syntax for the first variant, or do you have to either import each thing by name, or use the wrapper object?

das-g
  • 9,718
  • 4
  • 38
  • 80
mikl
  • 23,749
  • 20
  • 68
  • 89
  • 2
    Imagine `import * from` would be possible. What would happen if `reducers.js` contains a variable `MYAPP_FOO`? Or if another module also contains `MYAPP_FOO`? And there's much more to consider. It's not a good idea. – a better oliver Feb 22 '16 at 14:01
  • Its absence certainly makes static analysis easier, so it could be argued that usage of such syntax would be an anti-pattern. Even so, it could be handy once in a while. – mikl Feb 22 '16 at 14:46

5 Answers5

55

You cannot import all variables by wildcard for the first variant because it causes clashing variables if you have it with the same name in different files.

//a.js
export const MY_VAR = 1;

//b.js
export const MY_VAR = 2;


//index.js
import * from './a.js';
import * from './b.js';

console.log(MY_VAR); // which value should be there?

Because here we can't resolve the actual value of MY_VAR, this kind of import is not possible.

For your case, if you have a lot of values to import, will be better to export them all as object:

// reducers.js

import * as constants from './constants'

console.log(constants.MYAPP_FOO)
just-boris
  • 9,468
  • 5
  • 48
  • 84
  • 4
    Well, wildcard imports work in python: the reference to `a.js` is destroyed and `b.js` is used. Why wouldn't this work in JS? – noɥʇʎԀʎzɐɹƆ Jan 01 '18 at 21:01
  • 2
    I think it's dangerous as well. Say you `import *` from a few third-party libraries. LibA has a `foo` you want, and LibB doesn't have any `foo`. Months or years later, LibB adds a `foo` component, which clobber's LibA's `foo`. Suddenly your code breaks. LibB might not even consider the addition of `foo` to be a semver major change, since it didn't exist before. – error Feb 08 '18 at 18:59
  • 1
    @noɥʇʎԀʎzɐɹƆ Because it's likely you don't have control over the implementation of `a.js` or `b.js`, so there's no way you can prevent name clashing. Specially in the future, as noted by @error. – almulo Feb 26 '18 at 10:53
  • Can not understand the problem. An import is a definition. In JavaScript it is perfectly valid to redefine a variable with another value. If you import the same thing twice, the second import redefines the first. Where is the problem? – ceving Feb 03 '23 at 08:46
36

Is there a syntax for the first variant,

No.

or do you have to either import each thing by name, or use the wrapper object?

Yes.

Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
  • 1
    To elaborate just a tiny bit, see `with`. – Carl Smith Aug 25 '20 at 00:15
  • `with` is completely unrelated: it is a bad idea because it depends on a dynamic value. `import`s are static, so defining all exported names could be done. Note (1) doing this with *dynamic* import would run into the same problem as `with`; (2) overwriting imported names is of course a bad idea, but it could throw an error, this also has problem which is why all of this wasn't done, but they're much more subtle than `with`. – Eli Barzilay Oct 16 '21 at 17:48
2

well you could import the object, iterate over its properties and then manually generate the constants with eval like this

import constants from './constants.js'

for (const c in constants) {
  eval(`const ${c} = ${constants[c]}`)
}

unfortunately this solution doesn't work with intellisense in my IDE since the constants are generated dynamically during execution. But it should work in general.

ysf
  • 4,634
  • 3
  • 27
  • 29
0

Sure there are.

Just use codegen.macro

codegen
      'const { ' + Object.keys(require('./path/to/file')).join(',') + '} = require("./path/to/file");

But it seems that you can't import variable generated by codegen. https://github.com/kentcdodds/babel-plugin-codegen/issues/10

Ishara Madhawa
  • 3,549
  • 5
  • 24
  • 42
林东吴
  • 171
  • 1
  • 8
-3

In ES6, with below code, imported content can be used without wrap object.

Just put it here for someone like me who ends searching here.

constants.js:

export const A = 2;
export const B = 0.01; 
export const C = 0.04;

main.js:

import * as constants from './constants'
const {
    A,
    B,
    C,
} = constants;
Chenhua
  • 185
  • 2
  • 10