I have the following imports:
import { default as service } from "../service";
VS
import * as service from "../service";
My service is exported like so
module.exports = {
init(store) {
_store = store;
},
beginPayment() {
}
};
I would expect that only the second import would work since there is no export default, however both seem to work.
What is the difference between these? Is one preferred over the other?
If this is a duplicate I apologize, I didn't find anything specific to my example on SO or Google.
If you are importing the default, there has to be a default.
In general, the community appears wary of default exports at the moment as they seem to be less discoverable (I have no specific citation, but I've watched the conversation!)
If you are working in a team, whatever they say is the correct answer, of course!
So without a default, you need to use:
import * as service from "../service";
Or choose a specific thing:
import { specificNamedThing } from "../service";
Related
I'm trying to fully understand JavaScript import and exports. According to the syntax diagram on https://tc39.es/ecma262/#sec-exports it's valid to have an empty block which I assume means import nothing so what is it for? Example:
import { } from './somewhere.js'
It will run the code in somewhere.js. That might be useful for initializing something, but if that's all you need, you can get the same effect with:
import './somewhere.js'
So i don't really see a reason to write the example you're asking about.
If i had to guess, i'd assume the reason it's allowed is that a definition allowing N named imports (eg, import { foo, bar, baz } from './somewhere.js") would very easily have a base case of import { } from './somewhere.js, and there just wasn't a reason to ban the empty case.
Let's take code bellow as our example
./somewhere.js
console.log('imported');
export const PI = 3;
Importing code above using import { } from './somewhere.js' will result in logging into console. The same would be true for import './somewhere.js'.
I'm making a semi-complex Fragment using React/Styled-Components. I always try to improve the flexibility of larger Fragments/Components by exporting any sub-components that is styled so minor tweaks can easily be made anywhere in the DOM tree whenever my team need similar components.
I do this by collecting everything in an index file, and using Module Redirects as described at the end of this Mozilla article:
https://developer.mozilla.org/en-US/docs/web/javascript/reference/statements/export
However, for some reason when I try to do export { SomeComponent, SomeOtherComponent } from './SomeStuff.styled' or export * from './SomeStuff.styled' I get the error Cannot create styled-component for component: undefined.
What am I doing wrong?
The project is closed source so I can't show full files or a repo
All the exports in ./ListElement are named exports.
// In index.js
export { default as Counter } from './Counter';
export { Element, Container, Names, Prices } from './ListElement';
export { default as OrderListHeading } from './OrderListHeading';
// In the Fragment where I'm using it
import { Counter, Element } from '.';
...
const Heading = styled(Element)``;
The curious thing is that it works if I import and export seperately as such:
// In index.js
import { Element, Container, Names, Prices } from './ListElement';
export { default as Counter } from './Counter';
export { Element, Container, Names, Prices };
export { default as OrderListHeading } from './OrderListHeading';
export { default as Counter } from './Counter';
export { Element, Container, Names, Prices } from './ListElement';
export { default as OrderListHeading } from './OrderListHeading';
This is not yet in current ECMAScript standard.
It's still a proposal in stage 1. In order for a language feature proposal to land in the current ECMAScript standard, it must move to stage 4.
You are probably using a project configuration that doesn't support this. But if you can extend your Babel configuration you can start using this feature by installing #babel/plugin-proposal-export-default-from.
I have a package that I use somewhat like this:
import { something } from 'somewhere';
But then I have another package that I import, and I need to define the same something name which is defined in it.
import myConsts from 'SomewhereElse';
const { something, another } = myConsts;
I get an eslint error (and rightly so) something already defined.
Here's a real example:
import { connect } from 'react-redux';
// following lines from react-native-kontaktio sample code...
import Kontakt from 'react-native-kontaktio';
const { connect, configure, startScanning } = Kontakt;
I tried
import { connect as kontaktConnect, configure, startScanning } from 'react-native-kontaktio'
but get Possible promise rejection ... (reactNativeKontaktio.connect) is not a function.
If I try to change the
import { connect as reduxConnect } from 'react-redux';
I'll have to change the export as follows. Won't that break my code elsewhere?
// export default connect(mapStateToProps, mapDispatchToProps)(AppMain);
export default reduxConnect(mapStateToProps, mapDispatchToProps)(AppMain);
How can I overcome this? Can I ignore the warning in some cases? There is no Polymorphism in Ecma6 right?
This is NOT a question about two classes with the same name, but about two classes with a method or a constant of the same name.
The answer there seems to be applicable here, to use:
// instead of: import myConsts from 'SomewhereElse';
import { something as somethingElse, another } from 'SomewhereElse';
But then, when I use... somethingElse().then(()=> ... I get an error Possible promise rejection ... (SomewhereElse.something) is not a function
This also is NOT a [question about fixing the general is already defined eslint error] (Javascript standardjs - how to fix 'is already defined'?), since I am not talking about writing MY code, but rather how to import and use someone else's two packages when they have this clash problem.
No I think you can't ignore the warning, because 2 variables with the same name are present in the same scope.
You may need to import in this way:
import { connect as somethingElse} from 'react-redux';
To avoid to variables with the same name.
I hope it will help you
import { Injectable } from '#angular/core';
import { Headers, Http, Response } from '#angular/http';
import { Observable } from '#rxjs/Observable';
import 'rxjs/Rx';
import 'rxjs/add/observable/throw';
#Component({});
export shellModule{}
This is a piece of code form my Angular app that I copied from somewhere (I have removed the definitions in the exported module. I am using it to make a service to call APIs.
In the imports in this particular file, why is it that Observable is imported separately even though the entire rxjshas been imported. If a particular module is being imported in its entirety, why is a particular object from it imported separately? I tried asking this question at the forum from where I took it, but there was no answer. I want to understand if this somehow helps with optimization of code.
In general:
In Typescript, the way modules are handled would require you to either load in the entire library with the import * as rx from 'rxjs/Rx', or a specific exported module within the library to use it, so the the compiler loads in the types.
Reducing your imports to only the specific modules you need sets up your app to use tree shaking from Angular's AOT compilation. This is not done by the typescript compiler, but by a tool called rollup. So, it can help with optimizing code later, but it doesn't automatically do so.
As far as compilation overhead, bringing in the whole library might slow down the compiler a bit... but this isn't a very strong point except for massively complex libraries.
I, personally, prefer importing in specific modules because it makes the calling code a little cleaner since I don't need to use that global name to get to the specific name. rx.Observable vs Observable. A good example of this is the lodash library (rxjs is a bit more complex...)
Honestly, importing entire libraries like the line you have there: import 'rxjs/Rx' doesn't make sense to me. You should only import specific exported modules. Try removing it, seeing what errors you get, and then using the * as rx syntax instead.
As far as rxjs goes - it is a little wonky when you want to import specific operators like this question does - so the way to get specific operators is with: import 'rxjs/add/observable/from' - but that also requires a tinkering with your webpack set up as outlined in the referenced question's answer.
Let's see what the rxjs/Rx module exports:
export { Subject, AnonymousSubject } from './Subject';
export { Observable } from './Observable';
export { Operator } from './Operator';
export { Observer } from './Observer';
export { Subscription } from './Subscription';
export { Subscriber } from './Subscriber';
export { AsyncSubject } from './AsyncSubject';
export { ReplaySubject } from './ReplaySubject';
export { BehaviorSubject } from './BehaviorSubject';
...
import './add/observable/bindCallback';
import './add/observable/bindNodeCallback';
import './add/observable/combineLatest';
...
So it exports RxJs classes and also imports operators from the add folder. So as you can see it loads everything in the library. It doesn't export any global object though. So you need to use named export like this:
import * as Rx from 'rxjs/Rx'
to be able to use an exported class:
Rx.Observable.of(12, 3);
This emulates what you would have if you loaded the library using the bundle - a global Rx object:
<script src="rxjs/bundles/Rx.js">
If you want to use Observable without Rx global object, you need to import it separately:
import { Observable } from '#rxjs/Observable';
Observable.of(1);
Importing both
import { Observable } from '#rxjs/Observable';
import 'rxjs/Rx';
is not a good practice, but may be used if you don't want to import every operator separately.
Also see How to correctly import operators from the rxjs package.
Say I have two files:
box.ts:
export module Entities {
export class Box { .. Stuff }
origin.ts:
export module Entities {
export class Origin { .. other stuff }
As I understand javascript, those two modules should merge into one module that has both my classes in it.. (I just want them in separate files for organizational reasons, but both box and origin are entities.)
So now I have a file that needs to use both of those:
service-actions.ts:
import {Entities} from '../entities/box';
import {Entities} from '../entities/origin';
... stuff that uses both of those entities.
This gives me the error:
Duplicate identifier 'Entities';
If I have one or the other, it works fine, but both fail.
Is there a way I can combine these so that the I can do Entities.Box and Entities.Origin in my service-action.ts file?
Is the only way to do this is to put Box and Origin in the same file?
Don't mix namespaces (internal modules) with external modules. See this post and this question and others for arguments against mixing. I've found it best to not use internal modules altogether. We don't gain any encapsulation benefits from namespaces. Instead, directories are a simple and solid way to organize code, and you are using them already.
entities/box.ts:
export class Box { .. Stuff }
entities/origin.ts:
export class Origin { .. other stuff }
Now instead of having to write Entities.Box, you can just import Box and use it:
import { Box } from '../entities/box';
import { Origin } from '../entities/origin';
Use as:
import {Entities as BoxEntities} from './../entities/box';
import {Entities as OriginEntities} from './../entities/origin';
// Use BoxEntities and OriginEntities here
Preferably, if you are actually exporting the classes directly from the files as you should be (and as pointed out by mk.), you could create an entities.ts file that handles it for you:
export * from './entities/box';
export * from './entities/origin';
Then import this file:
import * as Entities from './../entities';
// use Entities.Box and Entities.Origin here