158

Say I have a module (./my-module.js) that has an object which should be its return value:

let values = { a: 1, b: 2, c: 3 }

// "export values" results in SyntaxError: Unexpected token

So I can import them like:

import {a} from './my-module'           // a === 1
import * as myModule from './my-module' // myModule.a === 1

The only way I found is by hard coding the exports:

export let a = values.a
export let b = values.b
export let c = values.c
// or:
export let {a, b, c} = values

Which is not dynamic.

Is it possible to export all values from an object?

mauvm
  • 3,586
  • 3
  • 18
  • 19
  • 7
    No, because dynamically computed value cannot be statically exported. – Bergi Apr 24 '15 at 21:54
  • @Bergi, I'm wondering if it's somehow possible to make the values static in someway. I was thinking about what if you use an `interface { a: number, b: number, c: number }`? Theoretically it should be possible, right? – luukvhoudt Sep 19 '19 at 22:01
  • 2
    @Fleuv `export const {a, b, c} = values` is precisely the syntax to declare that static interface – Bergi Sep 19 '19 at 22:05

10 Answers10

104

I can't really recommend this solution work-around but it does function. Rather than exporting an object, you use named exports each member. In another file, import the first module's named exports into an object and export that object as default. Also export all the named exports from the first module using export * from './file1';

values/value.js

let a = 1;
let b = 2;
let c = 3;

export {a, b, c};

values/index.js

import * as values from './value';

export default values;
export * from './value';

index.js

import values, {a} from './values';

console.log(values, a); // {a: 1, b: 2, c: 3} 1
ryanjduffy
  • 4,959
  • 3
  • 22
  • 13
  • 4
    Why wouldn't you recommend this? – jsdario Sep 08 '16 at 10:11
  • 2
    Maybe because the cure is worse than the illness (unless you're writing a publicly-consumable library and you're really picky about how its imported)? – machineghost Sep 26 '16 at 17:36
  • 1
    Yea, that's a good summary. It's a technique I used once in library to ease consumability. I think it'd be better to manage the exports within a single file even though it's more work for the library author. The result is one less module depth for the user. – ryanjduffy Sep 26 '16 at 21:18
  • I quite like this work-around, but it should be './value' instead of './values' in values/index.js, right? – Jan Paepke Sep 27 '19 at 08:42
  • @JanPaepke Good catch! I'll fix that up. – ryanjduffy Sep 29 '19 at 15:33
  • 1
    I really don't think this is the answer, since if I already export `{ a, b, c }`, why do I need to export again ? The real question is what if I only have `const obj = { a, b, c }` and can I export obj's all member ? I guess the answer is NO. – windmaomao Nov 11 '19 at 19:42
  • Man, it worked for me. Thanks. You know, this should be the accepted answer. – Alexandre Piva Jul 24 '20 at 17:02
  • this does not solve the question asked - how to export every value in an object dynamically - which can't be done. this technique provides a layer of separation between the modules (files) in a package (directory) any consumer of that package (even if part of the same project importing in another dir), freeing the consumer from knowledge of the package's internal file structure and being immune to changes in the package's file structure. it essentially provides a single, clean interface of the package's "public" exports – speakingcode Dec 30 '20 at 03:36
48

Does not seem so. Quote from ECMAScript 6 modules: the final syntax:

You may be wondering – why do we need named exports if we could simply default-export objects (like CommonJS)? The answer is that you can’t enforce a static structure via objects and lose all of the associated advantages (described in the next section).

Joel
  • 15,496
  • 7
  • 52
  • 40
19

I just had need to do this for a config file.

var config = {
    x: "CHANGE_ME",
    y: "CHANGE_ME",
    z: "CHANGE_ME"
}

export default config;

You can do it like this

import { default as config } from "./config";

console.log(config.x); // CHANGE_ME

This is using Typescript mind you.

mikeysee
  • 1,613
  • 1
  • 18
  • 31
18

try this ugly but workable solution:

// use CommonJS to export all keys
module.exports = { a: 1, b: 2, c: 3 };

// import by key
import { a, b, c } from 'commonjs-style-module';
console.log(a, b, c);
springuper
  • 508
  • 4
  • 11
8

Why not just do a named export of the object:

let values = { a: 1, b: 2, c: 3 }
export { values }

or

export let values = { a: 1, b: 2, c: 3 }

and then a named import where you need it:

import { values } from './my-module'

let foo = values.a
let { a, b, c } = values

or

import { values as myModule } from './my-module'

let foo = myModule.a
let { a, b, c } = myModule

can do default export as well:

let values = { a: 1, b: 2, c: 3 }
export default values 

or

export default { a: 1, b: 2, c: 3 }

and then consume it:

import whateverIcallIt from './my-Module'

let foo = whateverIcallIt.a
let {a, b, c } = whateverIcallIt

If you want to export a bunch of individual values, say a bunch of constants, you can:

export const a = 1
export const b = 2
//...

or even

export const a = 1,
             b = 2,
             c = 3,
//...

and then import them individually:

import { a, b, c } from './my-module'
speakingcode
  • 1,518
  • 13
  • 12
6

I suggest the following. Let's expect a module.js:

const values = { a: 1, b: 2, c: 3 };

export { values }; // you could use default, but I'm specific here

and then you can do in an index.js:

import { values } from "module";

// directly access the object
console.log(values.a); // 1

// object destructuring
const { a, b, c } = values; 
console.log(a); // 1
console.log(b); // 2
console.log(c); // 3

// selective object destructuring with renaming
const { a:k, c:m } = values;
console.log(k); // 1
console.log(m); // 3

// selective object destructering with renaming and default value
const { a:x, b:y, d:z = 0 } = values;
console.log(x); // 1
console.log(y); // 2
console.log(z); // 0

More examples of destructuring objects: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment#Object_destructuring

Ann Kilzer
  • 1,266
  • 3
  • 16
  • 39
RiZKiT
  • 2,107
  • 28
  • 23
4
export const a = 1;
export const b = 2;
export const c = 3;

This will work w/ Babel transforms today and should take advantage of all the benefits of ES2016 modules whenever that feature actually lands in a browser.

You can also add export default {a, b, c}; which will allow you to import all the values as an object w/o the * as, i.e. import myModule from 'my-module';

Sources:

jrz
  • 4,286
  • 1
  • 29
  • 21
3

Every answer requires changing of the import statements.

If you want to be able to use:

import {a} from './my-module'           // a === 1
import * as myModule from './my-module' // myModule.a === 1

as in the question, and in your my-module you have everything that you need to export in one object (which can be useful e.g. if you want to validate the exported values with Joi or JSON Schema) then your my-module would have to be either:

let values = { a: 1, b: 2, c: 3 }
let {a, b, c} = values;
export {a, b, c};

Or:

let values = { a: 1, b: 2, c: 3 }
export let {a, b, c} = values;

Not pretty, but it compiles to what you need.

See: Babel example

rsp
  • 107,747
  • 29
  • 201
  • 177
2

Exporting each variable from your variables file. Then importing them with * as in your other file and exporting the as a constant from that file will give you a dynamic object with the named exports from the first file being attributes on the object exported from the second.

Variables.js

export const var1 = 'first';
export const var2 = 'second':
...
export const varN = 'nth';

Other.js

import * as vars from './Variables';

export const Variables = vars;

Third.js

import { Variables } from './Other';

Variables.var2 === 'second'