For object const a = {b: 1, c: 2, d: 3}, we can do destructuring like this: const {b, ...rest} = a.
I'm wondering if it's also possible for imports.
Say I have a file file1.js:
// file1.js
export const a = 1;
export const b = 2;
export const c = 3;
Can I import from this file by importing one and the rest like destructuring?
// file2.js
import {a, ...rest} from "file1";
Not directly, there's no import form for it.
What you can do instead is import the module's module namespace object, then use destructuring on it:
import * as file1 from "file1";
const {a, ...rest} = file1;
FWIW, the specification has an example list of import forms here. It doesn't show what you can and can't combine, but those are the basic forms.
Is it possible to create a dynamic const name of an array using dropdown options?
Import {array1, array2, array3} from './myfilesystem/arrays';
const somename = array1;
You need to:
Put your arrays in a keyed object.
Put the keys in the drop-down.
Put the selected key in a variable.
Use the value of that variable to look up the array in the object.
Like this:
const arrays = {
array1: [...],
array2: [...],
array3: [...]
}
const optionsForDropdown = Object.keys(arrays) // ["array1", "array2",...]
function returnSelectedArray(selectedKey) {
return arrays[selectedKey]
}
So if you call returnSelectedArray("array1") or you do:
const key = "array1"
returnSelectedArray(key)
you will get arrays.array1 back.
import * as arr from '..pathname'
// ..and somewhere in your code..
const someArray = arr.array1
is that what u ment?
imports/exports :
exporting from a file, has many syntax variants
// explicit exports
export const PI = 3.14159
export const cylinderVolume = (r, h) => {....}
//export as an object..
const PI = 3.14159
const cylinderVolume = (r, h) => {....}
export { PI, cylinderVolume }
// default export
export default PI = 3.14159
export const cylinderVolume = (r, h) => {....}
imports
// importing explict exports
import { PI, cylinderVolume } from 'path'
//importing default and explict exports(PI is default and cylinderVolume is explict)
import PI, { cylinderVolume } from 'path'
// importing as whole..
import * as shape from 'path'
// useage..
const cylinderSurfaceArea = (r, h) => 2*shape.PI*r ( r + h )
Re-export from another file..
export { cylinderVolume } from 'path'
// re-exporting as default..
export { default as PI } from 'path'
comparing some impacts on size on usecases:
import _ from 'lodash' // use case..
import * as shape from 'path' // same effect..
this will import the entire module and has a huge effect on the project size. however if we are using libs like lodash this is the way they recommend.
import { get, has } from 'lodash'
import { PI, cylinderVolume } from 'path'
surprisingly this don't have any much size diffrence comparing with the above syntax.
Tree Shaking
Modern build tools (webpack and others) bundle modules together and optimize them to speedup loading and remove unused stuff.
so, in order to minimize the impact on size the recommended syntax would be
import get from 'lodash/get'
but still when we have to import a whole load of stuff it's not practical(or recommended/ideal for the sake of readability)..
I want to export all methods of a file from another file.
currently I am doing this, and it works. How can I merge below two into 1 export expression
import * as db from './web/query';
export default db;
I tried below written 1 line exports but all failed
export * from './web/query'; //==error
export * as default from './web/query'; //==error
export * as {default} from './web/query'; //==error
export from from './web/query'; //== error
export default from './web/query'; //== error
Error means
import db from '../db/index';
db is undefined here. However the the first methods works
Inside of file './web/query' looks like
export function foo(){}
export function baar(){}
You cannot in ES2016. To create a module namespace object, you need to give it an identifier (like db) in your current module scope, and then re-export that. There's no way around it.
There is however a stage 1 proposal to add the export * as default from … syntax you were trying.
How can I merge below two into 1 export expression
You cannot.
ES2015 (and ES2016) does not provide a syntax that would allow you to import all the named exports from a file and export the object (with those as its properties) as default in a single statement.
You can export the named exports of another file with export * from '<FILE>';.
// a.js
export const one = '1';
export const two = '2';
// b.js
export * from './a.js';
// c.js
import { one, two } from './b.js';
you can do something like this:
a.js:
const fakeName = "Blabla";
const fakeAge = 33;
module.exports = {fakeName, fakeAge}
b.js:
const name = "Someone";
let age = 22;
module.exports = { name, age}
c.mjs:
export * from './a.js';
export * from './b.js';
index.mjs:
import * as AllClass from './c.mjs'
export default AllClass
use it in e.g server.mjs:
import AllClass from './index.mjs'
console.log("fakeName:", AllClass.fakeName);
console.log("NAME:",AllClass.name);
It's just hard not to get confused with ESModule imports/exports and CommonJS imports and exports...
EDIT
Maybe I found the problem, would like if someone could confirm the situation: It seems like test.js is importing index.js which is importing test.js, and export has not an stop infinite-loop inclusion... Is it right? Is there any workaround like Don't include this file if it's the calling one?
I'm facing a strange problem. I'm trying to import some objects from a re-export (tcomb-react-native is not relevant here as the problem is with import/export).
|-- index.js
|-- simpleTypes.js
|-- userType.js
index.js:
export { UserType, UserTypeBase } from './test';
export { TextMax9Type } from './simpleTypes';
simpleTypes.js:
import t from 'tcomb-form-native';
export const TextMax9Type = t.refinement(t.String, s => s.length <= 9);
test.js:
import t from 'tcomb-form-native';
// import { TextMax9Type } from './'; // <----- NOT WORKING!
import { TextMax9Type } from './simpleTypes'; // <----- OK no error
export const UserTypeBase = {
Name: TextMax9Type,
Surname: TextMax9Type,
};
export const UserType = t.struct(UserTypeBase);
NOT WORKING error:
Invalid argument props {} supplied to struct(props, [name]) combinator (expected a dictionary String-> Type)
So which is the problem with re-export that is exporting an empty object?
With ES6, I can import several exports from a file like this:
import {ThingA, ThingB, ThingC} from 'lib/things';
However, I like the organization of having one module per file. I end up with imports like this:
import ThingA from 'lib/things/ThingA';
import ThingB from 'lib/things/ThingB';
import ThingC from 'lib/things/ThingC';
I would love to be able to do this:
import {ThingA, ThingB, ThingC} from 'lib/things/*';
or something similar, with the understood convention that each file contains one default export, and each module is named the same as its file.
Is this possible?
I don't think this is possible, but afaik the resolution of module names is up to module loaders so there might a loader implementation that does support this.
Until then, you could use an intermediate "module file" at lib/things/index.js that just contains
export * from 'ThingA';
export * from 'ThingB';
export * from 'ThingC';
and it would allow you to do
import {ThingA, ThingB, ThingC} from 'lib/things';
Just a variation on the theme already provided in the answer, but how about this:
In a Thing,
export default function ThingA () {}
In things/index.js,
export {default as ThingA} from './ThingA'
export {default as ThingB} from './ThingB'
export {default as ThingC} from './ThingC'
Then to consume all the things elsewhere,
import * as things from './things'
things.ThingA()
Or to consume just some of things,
import {ThingA,ThingB} from './things'
The current answers suggest a workaround but it's bugged me why this doesn't exist, so I've created a babel plugin which does this.
Install it using:
npm i --save-dev babel-plugin-wildcard
then add it to your .babelrc with:
{
"plugins": ["wildcard"]
}
see the repo for detailed install info
This allows you to do this:
import * as Things from './lib/things';
// Do whatever you want with these :D
Things.ThingA;
Things.ThingB;
Things.ThingC;
again, the repo contains further information on what exactly it does, but doing it this way avoids creating index.js files and also happens at compile-time to avoid doing readdirs at runtime.
Also with a newer version you can do exactly like your example:
import { ThingsA, ThingsB, ThingsC } from './lib/things/*';
works the same as the above.
You now can use async import():
import fs = require('fs');
and then:
fs.readdir('./someDir', (err, files) => {
files.forEach(file => {
const module = import('./' + file).then(m =>
m.callSomeMethod();
);
// or const module = await import('file')
});
});
Great gugly muglys! This was harder than it needed to be.
Export one flat default
This is a great opportunity to use spread (... in { ...Matters, ...Contacts } below:
// imports/collections/Matters.js
export default { // default export
hello: 'World',
something: 'important',
};
// imports/collections/Contacts.js
export default { // default export
hello: 'Moon',
email: 'hello#example.com',
};
// imports/collections/index.js
import Matters from './Matters'; // import default export as var 'Matters'
import Contacts from './Contacts';
export default { // default export
...Matters, // spread Matters, overwriting previous properties
...Contacts, // spread Contacts, overwriting previosu properties
};
// imports/test.js
import collections from './collections'; // import default export as 'collections'
console.log(collections);
Then, to run babel compiled code from the command line (from project root /):
$ npm install --save-dev #babel/core #babel/cli #babel/preset-env #babel/node
(trimmed)
$ npx babel-node --presets #babel/preset-env imports/test.js
{ hello: 'Moon',
something: 'important',
email: 'hello#example.com' }
Export one tree-like default
If you'd prefer to not overwrite properties, change:
// imports/collections/index.js
import Matters from './Matters'; // import default as 'Matters'
import Contacts from './Contacts';
export default { // export default
Matters,
Contacts,
};
And the output will be:
$ npx babel-node --presets #babel/preset-env imports/test.js
{ Matters: { hello: 'World', something: 'important' },
Contacts: { hello: 'Moon', email: 'hello#example.com' } }
Export multiple named exports w/ no default
If you're dedicated to DRY, the syntax on the imports changes as well:
// imports/collections/index.js
// export default as named export 'Matters'
export { default as Matters } from './Matters';
export { default as Contacts } from './Contacts';
This creates 2 named exports w/ no default export. Then change:
// imports/test.js
import { Matters, Contacts } from './collections';
console.log(Matters, Contacts);
And the output:
$ npx babel-node --presets #babel/preset-env imports/test.js
{ hello: 'World', something: 'important' } { hello: 'Moon', email: 'hello#example.com' }
Import all named exports
// imports/collections/index.js
// export default as named export 'Matters'
export { default as Matters } from './Matters';
export { default as Contacts } from './Contacts';
// imports/test.js
// Import all named exports as 'collections'
import * as collections from './collections';
console.log(collections); // interesting output
console.log(collections.Matters, collections.Contacts);
Notice the destructuring import { Matters, Contacts } from './collections'; in the previous example.
$ npx babel-node --presets #babel/preset-env imports/test.js
{ Matters: [Getter], Contacts: [Getter] }
{ hello: 'World', something: 'important' } { hello: 'Moon', email: 'hello#example.com' }
In practice
Given these source files:
/myLib/thingA.js
/myLib/thingB.js
/myLib/thingC.js
Creating a /myLib/index.js to bundle up all the files defeats the purpose of import/export. It would be easier to make everything global in the first place, than to make everything global via import/export via index.js "wrapper files".
If you want a particular file, import thingA from './myLib/thingA'; in your own projects.
Creating a "wrapper file" with exports for the module only makes sense if you're packaging for npm or on a multi-year multi-team project.
Made it this far? See the docs for more details.
Also, yay for Stackoverflow finally supporting three `s as code fence markup.
Similar to the accepted answer but it allows you to scale without the need of adding a new module to the index file each time you create one:
./modules/moduleA.js
export const example = 'example';
export const anotherExample = 'anotherExample';
./modules/index.js
// require all modules on the path and with the pattern defined
const req = require.context('./', true, /.js$/);
const modules = req.keys().map(req);
// export all modules
module.exports = modules;
./example.js
import { example, anotherExample } from './modules'
If you are using webpack. This imports files automatically and exports as api namespace.
So no need to update on every file addition.
import camelCase from "lodash-es";
const requireModule = require.context("./", false, /\.js$/); //
const api = {};
requireModule.keys().forEach(fileName => {
if (fileName === "./index.js") return;
const moduleName = camelCase(fileName.replace(/(\.\/|\.js)/g, ""));
api[moduleName] = {
...requireModule(fileName).default
};
});
export default api;
For Typescript users;
import { camelCase } from "lodash-es"
const requireModule = require.context("./folderName", false, /\.ts$/)
interface LooseObject {
[key: string]: any
}
const api: LooseObject = {}
requireModule.keys().forEach(fileName => {
if (fileName === "./index.ts") return
const moduleName = camelCase(fileName.replace(/(\.\/|\.ts)/g, ""))
api[moduleName] = {
...requireModule(fileName).default,
}
})
export default api
I've used them a few times (in particular for building massive objects splitting the data over many files (e.g. AST nodes)), in order to build them I made a tiny script (which I've just added to npm so everyone else can use it).
Usage (currently you'll need to use babel to use the export file):
$ npm install -g folder-module
$ folder-module my-cool-module/
Generates a file containing:
export {default as foo} from "./module/foo.js"
export {default as default} from "./module/default.js"
export {default as bar} from "./module/bar.js"
...etc
Then you can just consume the file:
import * as myCoolModule from "my-cool-module.js"
myCoolModule.foo()
Just an other approach to #Bergi's answer
// lib/things/index.js
import ThingA from './ThingA';
import ThingB from './ThingB';
import ThingC from './ThingC';
export default {
ThingA,
ThingB,
ThingC
}
Uses
import {ThingA, ThingB, ThingC} from './lib/things';
Nodejs ? Do like this:
Create a folder with index.js, in index file, add this:
var GET = require('./GET');
var IS = require('./IS');
var PARSE = require('./PARSE');
module.exports = { ...GET, ...IS, ...PARSE};
And, in file GET.js, or IS.js export as normal:
module.exports = { /* something as you like */}
ANd now, you need only including index.js like:
const Helper = require('./YourFolder');
Helper will include all of function in YourFolder.
Good day!
This is not exactly what you asked for but, with this method I can Iterate throught componentsList in my other files and use function such as componentsList.map(...) which I find pretty usefull !
import StepOne from './StepOne';
import StepTwo from './StepTwo';
import StepThree from './StepThree';
import StepFour from './StepFour';
import StepFive from './StepFive';
import StepSix from './StepSix';
import StepSeven from './StepSeven';
import StepEight from './StepEight';
const componentsList= () => [
{ component: StepOne(), key: 'step1' },
{ component: StepTwo(), key: 'step2' },
{ component: StepThree(), key: 'step3' },
{ component: StepFour(), key: 'step4' },
{ component: StepFive(), key: 'step5' },
{ component: StepSix(), key: 'step6' },
{ component: StepSeven(), key: 'step7' },
{ component: StepEight(), key: 'step8' }
];
export default componentsList;
You can use require as well:
const moduleHolder = []
function loadModules(path) {
let stat = fs.lstatSync(path)
if (stat.isDirectory()) {
// we have a directory: do a tree walk
const files = fs.readdirSync(path)
let f,
l = files.length
for (var i = 0; i < l; i++) {
f = pathModule.join(path, files[i])
loadModules(f)
}
} else {
// we have a file: load it
var controller = require(path)
moduleHolder.push(controller)
}
}
Then use your moduleHolder with dynamically loaded controllers:
loadModules(DIR)
for (const controller of moduleHolder) {
controller(app, db)
}
I was able to take from user atilkan's approach and modify it a bit:
For Typescript users;
require.context('#/folder/with/modules', false, /\.ts$/).keys().forEach((fileName => {
import('#/folder/with/modules' + fileName).then((mod) => {
(window as any)[fileName] = mod[fileName];
const module = new (window as any)[fileName]();
// use module
});
}));
if you don't export default in A, B, C but just export {} then it's possible to do so
// things/A.js
export function A() {}
// things/B.js
export function B() {}
// things/C.js
export function C() {}
// foo.js
import * as Foo from ./thing
Foo.A()
Foo.B()
Foo.C()