Shouldn't
import * as convict from "convict";
const config = convict({ ... });
// Perform validation
config.validate({ "allowed": "strict" });
export = config;
be functionally equivalent to:
import * as convict from "convict";
export const config = convict({ ... });
// Perform validation
config.validate({ "allowed": "strict" });
The first snippet works, but the second snippet introduces type errors such as:
TypeError: config.get is not a function
When imported using:
import * as config from "./config";
(This question and Frequent issue with TypeScript and preferring import over require are different. This question is about exports and what should be two equivalent usages. The other question is about imports.)
export const config = ... is so called "named export", it adds config variable to the list of names exported by the module. You can look at various variants of es6 export statement here, this particular one corresponds to the 4th line of the first example (note 'also var, const' comment):
export let name1 = …, name2 = …, …, nameN; // also var, const
and can be used with "named import* like
import {config} from '...';
export = config is entirely different, it's typescript-only export assignment. The documentation says that is should be imported as import config = require(...) which is again typescript-only special syntax.
With current version of TypeScript, export assignment can also be imported as
import * as config from 'module';
but there is breaking change in the works, in the future (maybe as soon as 2.8) this import will stop working with export assingment and will have to be written as
import config from 'module';
The two are indeed different. Essentially, it all has to do with the fact that in the second case config is a named export.
The first snippet produces an export that is just the config. If you did require("./config"), you'd get that config object. This is because you set the exports object to the config. That's why you have to do * as config when importing, because the entire imported object is what you're looking to get.
The second snippet produces an object with a named config field that points to your config; this is equivalent (ish) to doing:
exports = {
config: convict({ ... })
};
In this example, config is a named export. To import it, you'd have to get the config field of the exported object:
import { config } from "./config";
Related
I have two file:
file A.js:
export default={
name:"sample"
}
file B.svelte:
import {name} from './A';
Error:
name is not export from A.js
There are two problems there:
That's now how you make the default export an object, you should remove the =.
import is not destructuring, they just have a superficial resemblance to each other. You can't destructure during an import.
I would make the export a named export:
export let name = "sample";
...which would work with your import. Changes to name by the source module will show up in the imported binding for it (imports are live bindings to the original export).
But if you don't want to do that, here's how you export an object as the default export:
export default {
name: "sample",
};
and then you have to import and destructure separately:
import obj from "./A.js";
const { name } = obj;
Note: The above is how standard JavaScript modules work according to specification. Bundlers may go beyond the spec when bundling code (for instance, may allow named import syntax when in fact you're destructuring a default exported objects), but if so, it's non-standard.
I have referred all the questions in stackoverflow.
But none of the suggested why and when to use default export.
I just saw that default can be metioned "When there is only one export in a file"
Any other reason for using default export in es6 modules?
Some differences that might make you choose one over the other:
Named Exports
Can export multiple values
MUST use the exported name when importing
Default Exports
Export a single value
Can use any name when importing
This article does a nice job of explaining when it would be a good idea to use one over the other.
It's somewhat a matter of opinion, but there are some objective aspects to it:
You can have only one default export in a module, whereas you can have as many named exports as you like.
If you provide a default export, the programmer using it has to come up with a name for it. This can lead to inconsistency in a codebase, where Mary does
import example from "./example";
...but Joe does
import ex from "./example";
In contrast, with a named export, the programmer doesn't have to think about what to call it unless there's a conflict with another identifier in their module.¹ It's just
import { example } from "./example";
With a named export, the person importing it has to specify the name of what they're importing. They get a nice early error if they try to import something that doesn't exist.
If you consistently only use named exports, programmers importing from modules in the project don't have to think about whether what they want is the default or a named export.
¹ If there is a conflict (for instance, you want example from two different modules), you can use as to rename:
import { example as widgetExample } from "./widget/example";
import { example as gadgetExample } from "./gadget/example";
You should almost always favour named exports, default exports have many downsides
Problems with default exports:
Difficult to refactor or ensure consistency since they can be named anything in the codebase other than what its actually called
Difficult to analyze by automated tools or provide code intellisense and autocompletion
They break tree shaking as instead of importing the single function you want to use you're forcing webpack to import the entire file with whatever other dead code it has leading to bigger bundle sizes
You can't export more than a single export per file
You lose faster/direct access to imports
checkout these articles for a more detailed explanation:
https://blog.neufund.org/why-we-have-banned-default-exports-and-you-should-do-the-same-d51fdc2cf2ad
https://humanwhocodes.com/blog/2019/01/stop-using-default-exports-javascript-module/
https://rajeshnaroth.medium.com/avoid-es6-default-exports-a24142978a7a
With named exports, one can have multiple named exports per file. Then import the specific exports they want surrounded in braces. The name of imported module has to be the same as the name of the exported module.
// imports
// ex. importing a single named export
import { MyComponent } from "./MyComponent";
// ex. importing multiple named exports
import { MyComponent, MyComponent2 } from "./MyComponent";
// ex. giving a named import a different name by using "as":
import { MyComponent2 as MyNewComponent } from "./MyComponent";
// exports from ./MyComponent.js file
export const MyComponent = () => {}
export const MyComponent2 = () => {}
You can also alias named imports, assign a new name to a named export as you import it, allowing you to resolve naming collisions, or give the export a more informative name.
import MyComponent as MainComponent from "./MyComponent";
You can also Import all the named exports onto an object:
import * as MainComponents from "./MyComponent";
// use MainComponents.MyComponent and MainComponents.MyComponent2 here
One can have only one default export per file. When we import we have to specify a name and import like:
// import
import MyDefaultComponent from "./MyDefaultExport";
// export
const MyComponent = () => {}
export default MyComponent;
The naming of import is completely independent in default export and we can use any name we like.
From MDN:
Named exports are useful to export several values. During the import, one will be able to use the same name to refer to the corresponding value.
Concerning the default export, there is only a single default export per module. A default export can be a function, a class, an object or anything else. This value is to be considered as the “main” exported value since it will be the simplest to import.
There aren't any definitive rules, but there are some conventions that people use to make it easier to structure or share code.
When there is only one export in the entire file, there is no reason to make it named.
Also, when your module has one main purpose, it could make sense to make that your default export. In those cases you can extra named exports
In react for example, React is the default export, since that is often the only part that you need. You don't always Component, so that's a named export that you can import when needed.
import React, {Component} from 'react';
In the other cases where one module has multiple equal (or mostly equal) exports, it's better to use named exports
import { blue, red, green } from 'colors';
1st Method:-
export foo; //so that this can be used in other file
import {foo} from 'abc'; //importing data/fun from module
2nd Method:-
export default foo; //used in one file
import foo from 'blah'; //importing data/fun from module
3rd Method:-
export = foo;
import * as foo from 'blah';
The above methods roughly compile to the following syntax below:-
//all export methods
exports.foo = foo; //1st method
exports['default'] = foo; //2nd method
module.exports = foo; //3rd method
//all import methods
var foo = require('abc').foo; //1st method
var foo = require('abc')['default']; //2nd method
var foo = require('abc'); //3rd method
For more information, visit to Default keyword explaination
Note:- There can be only one export default in one file.
So whenever we are exporting only 1 function, then it's better to use default keyword while exporting
EASIEST DEFINITION TO CLEAR CONFUSIONS
Let us understand the export methods, first, so that we can analyze ourselves when to use what, or why do we do what we do.
Named exports: One or more exports per module. When there are more than one exports in a module, each named export must be restructured while importing. Since there could be either export in the same module and the compiler will not know which one is required unless we mention it.
//Named export , exporting:
export const xyz = () =>{
}
// while importing this
import {xyx} from 'path'
or
const {xyz} = require(path)
The braces are just restructuring the export object.
On the other hand , default exports are only one export per module , so they are pretty plain.
//exporting default
const xyz =() >{
};
export default xyz
//Importing
import xyz from 'path'
or
const xyz = require(path)
I hope this was pretty simple to understand, and by now you can understand why you import React modules within braces...
Named Export: (export)
With named exports, one can have multiple named exports per file. Then import the specific exports they want surrounded in braces. The name of imported module has to be the same as the name of the exported module.
// imports
// ex. importing a single named export
import { MyComponent } from "./MyComponent";
// ex. importing multiple named exports
import { MyComponent, MyComponent2 } from "./MyComponent";
// ex. giving a named import a different name by using "as":
import { MyComponent2 as MyNewComponent } from "./MyComponent";
// exports from ./MyComponent.js file
export const MyComponent = () => {}
export const MyComponent2 = () => {}
Import all the named exports onto an object:
// use MainComponents.MyComponent and MainComponents.MyComponent2 here
import * as MainComponents from "./MyComponent";
Default Export: (export default)
One can have only one default export per file. When we import we have to specify a name and import like:
// import
import MyDefaultComponent from "./MyDefaultExport";
// export
const MyComponent = () => {}
export default MyComponent;
Note: The naming of import is completely independent in default export and we can use any name we like.
Here's a great answer that explains default and named imports in ES6
See question title. I found a great reference for the forms of export available, but I have not seen what I'm looking for.
Is it possible to do something like the following?
// file: constants.js
export const SomeConstant1 = 'yay';
export const SomeConstant2 = 'yayayaya';
// file: index.js
export * as Constants from './constants.js';
I.e. this would provide a named export Constants inside of index.js containing all of the named exports from constants.js.
This answer seems to indicate it's not possible in TypeScript; is the same true for pure JavaScript?
(This example is a bit contrived; in reality I'm trying to have a prop-types.js module that uses named exports for internal use within the React package, but also exports the prop type definitions under PropTypes for external consumption. I tried to simplify for the sake of the question.)
No, it's not allowed in JS either, however there is a proposal to add it. For now, just use the two-step process with importing into a local variable and exporting that:
// file: constants.js
export const SomeConstant1 = 'yay';
export const SomeConstant2 = 'yayayaya';
// file: index.js
import * as Constants from './constants.js';
export {Constants};
Today in 2019, it is now possible.
export * as name1 from …;
The proposal for this spec has merged to ecma262. If you're looking for this functionality in an environment that is running a previous JS, there's a babel plugin for it! After configuring the plugin (or if you're using ecma262 or later), you are able to run the JS in your question:
// file: constants.js
export const SomeConstant1 = 'yay';
export const SomeConstant2 = 'yayayaya';
// file: index.js
export * as Constants from './constants.js';
// file: component.js
import { Constants } from './index.js';
const newVar = Constants.SomeConstant1; // 'yay'
// file: index.js
// note, this doesn't have to be at the top, you can put it wherever you prefer
import * as AllExportsFromThisModule from "./index.js"; // point this at the SAME file
export default AllExportsFromThisModule;
export const SOME_CONSTANT = 'yay';
export const SOME_OTHER_CONSTANT = 'yayayaya';
I have an external library thing.d.ts file with a global definition inside:
declare var thing: ThingStatic;
export default thing;
I reference npm module in my TypeScript:
import thing from 'thing';
...
thing.functionOnThing();
When I transpile the TS (targeting ES6) it looks something like this:
const thing_1 = require("thing");
...
thing_1.default.functionOnThing();
This then throws an error:
Cannot read property 'functionOnThing' of undefined
Why is TypeScript adding .default between thing_1 and functionOnThing()?
There is no property named default on ThingStatic, and no default property on the underlying JS object that the .d.ts file defines.
Why is TypeScript adding the property and how do I stop it?
import thing from 'thing';
This line of code means "import the default export from the module 'thing' and bind it to the local name thing".
TypeScript does as you requested and accesses the default property of the module object.
What you probably meant to write was
import * as thing from 'thing';
This appears to be a bug with global TS definitions and "module": "commonjs" in the tsconfig.json.
You can either use global TS definitions and stitch all your output into a single file, or you can use modules and directly import them.
The error here is due to the require returning the module context, and the name of the default being irrelevant - it always becomes default...
declare var thing: ThingStatic;
export thing; // Explicit export for thing
export default thing; // Default export for thing
Now require will return this context, so with commonjs modules:
import module from 'thing';
var thing = module.default; // From the default export
var alsoThing = module.thing; // From the named export
However, I've found this to be inconsistent, so switched to es6 modules:
import thing from './thing'; // Import default
import { thing } from './thing'; // Import named
const thing = (await import('path/to/thing.js')).default; // Import dynamic
It seems to be obvious, but I found myself a bit confused about when to use curly braces for importing a single module in ES6. For example, in the React-Native project I am working on, I have the following file and its content:
File initialState.js
var initialState = {
todo: {
todos: [
{id: 1, task: 'Finish Coding', completed: false},
{id: 2, task: 'Do Laundry', completed: false},
{id: 2, task: 'Shopping Groceries', completed: false},
]
}
};
export default initialState;
In the TodoReducer.js, I have to import it without curly braces:
import initialState from './todoInitialState';
If I enclose the initialState in curly braces, I get the following error for the following line of code:
Cannot read property todo of undefined
File TodoReducer.js:
export default function todos(state = initialState.todo, action) {
// ...
}
Similar errors also happen to my components with the curly braces. I was wondering when I should use curly braces for a single import, because obviously, when importing multiple component/modules, you have to enclose them in curly braces, which I know.
The Stack Overflow post at here does not answer my question, instead I am asking when I should or should not use curly braces for importing a single module, or I should never use curly braces for importing a single module in ES6 (this is apparently not the case, as I have seen single import with curly braces required).
This is a default import:
// B.js
import A from './A'
It only works if A has the default export:
// A.js
export default 42
In this case it doesn’t matter what name you assign to it when importing:
// B.js
import A from './A'
import MyA from './A'
import Something from './A'
Because it will always resolve to whatever is the default export of A.
This is a named import called A:
import { A } from './A'
It only works if A contains a named export called A:
export const A = 42
In this case the name matters because you’re importing a specific thing by its export name:
// B.js
import { A } from './A'
import { myA } from './A' // Doesn't work!
import { Something } from './A' // Doesn't work!
To make these work, you would add a corresponding named export to A:
// A.js
export const A = 42
export const myA = 43
export const Something = 44
A module can only have one default export, but as many named exports as you'd like (zero, one, two, or many). You can import them all together:
// B.js
import A, { myA, Something } from './A'
Here, we import the default export as A, and named exports called myA and Something, respectively.
// A.js
export default 42
export const myA = 43
export const Something = 44
We can also assign them all different names when importing:
// B.js
import X, { myA as myX, Something as XSomething } from './A'
The default exports tend to be used for whatever you normally expect to get from the module. The named exports tend to be used for utilities that might be handy, but aren’t always necessary. However it is up to you to choose how to export things: for example, a module might have no default export at all.
This is a great guide to ES modules, explaining the difference between default and named exports.
I would say there is also a starred notation for the import ES6 keyword worth mentioning.
If you try to console log Mix:
import * as Mix from "./A";
console.log(Mix);
You will get:
When should I use curly braces for ES6 import?
The brackets are golden when you need only specific components from the module, which makes smaller footprints for bundlers like webpack.
Dan Abramov's answer explains about the default exports and named exports.
Which to use?
Quoting David Herman:
ECMAScript 6 favors the single/default export style, and gives the sweetest syntax to importing the default. Importing named exports can and even should be slightly less concise.
However, in TypeScript named export is favored because of refactoring. Example, if you default export a class and rename it, the class name will change only in that file and not in the other references, with named exports class name will be renamed in all the references.
Named exports is also preferred for utilities.
Overall use whatever you prefer.
Additional
Default export is actually a named export with name default, so default export can be imported as:
import {default as Sample} from '../Sample.js';
If you think of import as just syntax sugar for Node.js modules, objects, and destructuring, I find it's pretty intuitive.
// bar.js
module = {};
module.exports = {
functionA: () => {},
functionB: ()=> {}
};
// Really all that is is this:
var module = {
exports: {
functionA, functionB
}
};
// Then, over in foo.js
// The whole exported object:
var fump = require('./bar.js'); //= { functionA, functionB }
// Or
import fump from './bar' // The same thing - object functionA and functionB properties
// Just one property of the object
var fump = require('./bar.js').functionA;
// Same as this, right?
var fump = { functionA, functionB }.functionA;
// And if we use ES6 destructuring:
var { functionA } = { functionA, functionB };
// We get same result
// So, in import syntax:
import { functionA } from './bar';
Summary ES6 modules:
Exports:
You have two types of exports:
Named exports
Default exports, a maximum one per module
Syntax:
// Module A
export const importantData_1 = 1;
export const importantData_2 = 2;
export default function foo () {}
Imports:
The type of export (i.e., named or default exports) affects how to import something:
For a named export we have to use curly braces and the exact name as the declaration (i.e. variable, function, or class) which was exported.
For a default export we can choose the name.
Syntax:
// Module B, imports from module A which is located in the same directory
import { importantData_1 , importantData_2 } from './A'; // For our named imports
// Syntax single named import:
// import { importantData_1 }
// For our default export (foo), the name choice is arbitrary
import ourFunction from './A';
Things of interest:
Use a comma-separated list within curly braces with the matching name of the export for named export.
Use a name of your choosing without curly braces for a default export.
Aliases:
Whenever you want to rename a named import this is possible via aliases. The syntax for this is the following:
import { importantData_1 as myData } from './A';
Now we have imported importantData_1, but the identifier is myData instead of importantData_1.
In order to understand the use of curly braces in import statements, first, you have to understand the concept of destructuring introduced in ES6
Object destructuring
var bodyBuilder = {
firstname: 'Kai',
lastname: 'Greene',
nickname: 'The Predator'
};
var {firstname, lastname} = bodyBuilder;
console.log(firstname, lastname); // Kai Greene
firstname = 'Morgan';
lastname = 'Aste';
console.log(firstname, lastname); // Morgan Aste
Array destructuring
var [firstGame] = ['Gran Turismo', 'Burnout', 'GTA'];
console.log(firstGame); // Gran Turismo
Using list matching
var [,secondGame] = ['Gran Turismo', 'Burnout', 'GTA'];
console.log(secondGame); // Burnout
Using the spread operator
var [firstGame, ...rest] = ['Gran Turismo', 'Burnout', 'GTA'];
console.log(firstGame);// Gran Turismo
console.log(rest);// ['Burnout', 'GTA'];
Now that we've got that out of our way, in ES6 you can export multiple modules. You can then make use of object destructuring like below.
Let's assume you have a module called module.js
export const printFirstname(firstname) => console.log(firstname);
export const printLastname(lastname) => console.log(lastname);
You would like to import the exported functions into index.js;
import {printFirstname, printLastname} from './module.js'
printFirstname('Taylor');
printLastname('Swift');
You can also use different variable names like so
import {printFirstname as pFname, printLastname as pLname} from './module.js'
pFname('Taylor');
pLanme('Swift');
Usually when you export a function you need to use the {}.
If you have
export const x
you use
import {x} from ''
If you use
export default const x
you need to use
import x from ''
Here you can change X to whatever variable you want.
The curly braces ({}) are used to import named bindings and the concept behind it is destructuring assignment
A simple demonstration of how import statement works with an example can be found in my own answer to a similar question at When do we use '{ }' in javascript imports?.
If there is any default export in the file, there isn't any need to use the curly braces in the import statement.
if there are more than one export in the file then we need to use curly braces in the import file so that which are necessary we can import.
You can find the complete difference when to use curly braces and default statement in the below YouTube video.
21. ES6 Modules. Different ways of using import/export, Default syntax in the code. ES6 | ES2015
The curly braces are used only for import when export is named. If the export is default then curly braces are not used for import.
For a default export we do not use { } when we import.
For example,
File player.js
export default vx;
File index.js
import vx from './player';
File index.js
File player.js
If we want to import everything that we export then we use *: