I'm getting mad with module import/export syntax...
Say on a file I want to import a module like this:
import { AccordionMenu } from '../node_modules/lr-js-modules/accordion-menu';
Now, how should I export from accordion-menu? My current code is an old school js class like this:
AccordionMenu = function(options){
[...]
}
AccordionMenu.prototype = { ... }
Then I was exporting like this:
export { AccordionMenu as default };
It doesn't work. Compiler says
export 'AccordionMenu' (imported as 'AccordionMenu') was not found in '../node_modules/lr-js-modules/accordion-menu' (possible exports: default)
I then tried several variants, but none worked to me. From mdn docs, as far as I can tell, all teh variants should work, but it's evident that I'm doing something wrong.
Can you help please?
The error message is quite clear: you exported default but your import tries to access an export AccordionMenu.
You should use either
export function AccordionMenu(options) { … }
// same as:
// function AccordionMenu(options) { … }
// export { AccordionMenu as AccordionMenu }
AccordionMenu.prototype = { … };
with
import { AccordionMenu } from '../node_modules/lr-js-modules/accordion-menu';
// same as:
// import { AccordionMenu as AccordionMenu } from '../node_modules/lr-js-modules/accordion-menu';
or, if that function is the only (or main) export of that module, use a default export
export default function AccordionMenu(options) { … }
// same as:
// function AccordionMenu(options) { … }
// export { AccordionMenu as default }
AccordionMenu.prototype = { … };
with
import AccordionMenu from '../node_modules/lr-js-modules/accordion-menu';
// same as:
// import { default as AccordionMenu } from '../node_modules/lr-js-modules/accordion-menu';
but the mix doesn't work.
Related
I have this code in file "Strings.js":
const Strings = {
getString(str) {
... // some logic
},
... // more functions
}
export default Strings;
I want to import both the whole thing (Strings) and/or just the getString function from another file like that:
import Strings, { getString } from '../../utils/Strings';
or maybe just:
import { getString } from '../../utils/Strings';
to be able to write simply getString and not Strings.getString (in multiple lines).
When I try to use it, I get the following error:
Attempted import error: 'getString' is not exported from '../../utils/Strings'.
Sorry if this question was already asked, I could not find an answer.
You should use named exports, not an object:
export function getString(str) {
… // some logic
}
… // more functions
You can then import them as a namespace object
import * as Strings from '../../utils/Strings';
… Strings.getString(…) …
or directly
import { getString } from '../../utils/Strings';
… getString(…) …
If you absolutely want/need to write import Strings from '…'; (you really shouldn't), you will need to add a default export object:
… // function declarations
export default { getString }
You either have to
function getString (str) {
}
const Strings = {
getString
}
export default Strings
export { getString }
or
const Strings = {
getStrings(str) {
}
}
const { getStrings } = String
export default Strings
export { getString }
So, there is no direct way to export an object property
I am trying to migrate a code from es5 to es6, I am quite new in both, if someone could help me, I will be very thankful.
es5 version:
lib.js
module.exports = {
foo1: function () {
this.foo2() {
...
}
},
foo2: function () {
...
}
}
main.js
const Lib = require("./lib");
Lib.foo1( { ... });
es6 version - I am trying:
lib.ts
export default {
foo1() {
this.foo2(() => {
...
});
},
foo2(){ ... }
}
main.ts
import * as Lib from "./lib";
Lib.foo1({ ... })
The problem is in my main.ts foo1 can not be resolved.
Any idea or recommendation?
Thank!
It should be just
import Lib from "./lib";
Otherwise, if you use * as notation you could access default export with Lib.default, but this is unnecessary.
I don't understand the following part of your code:
foo1: function () {
this.foo2() {
...
}
}
That seems invalid.
Anyway, do not introduce your own pseudo-module like structure. It's not necessary. lib.js is already a module.
lib.js
export function foo1() {
foo2();
}
export function foo2() { ... }
main.js
import {foo, foo2} from './lib';
I have a module A that is like
const defaults = {
something: {...},
somethingElse : {...}
}
export { defaults as default };
And then I am importing like
import * as mod, { something } from 'moduleA';
mod is correctly an object that has the two declared properties, but { something } is undefined.
Any idea what can be the reason?
[With the module as in the question] I am importing like
import * as mod, { something } from 'moduleA';
but something is undefined
But you don't have an export with the name something in your module. There only is a default-export that contains an object. You would need to do
import mod from 'moduleA';
const { something } = mod;
I have a module A that is like
const defaults = {
something: {...},
somethingElse : {...}
}
export { defaults as default };
But you really shouldn't do that anyway. Exporting "singleton" objects that act like a namespace is an antipattern in ES6 modules. You should use named exports instead:
export const something = {...};
export const somethingElse = {...};
With this, your original attempt at importing the module would have worked.
If you want to be able to access named exports in your import, you have to export them directly:
const defaults = {
something: {...},
somethingElse : {...}
}
export {
defaults as default,
defaults.something as something,
defaults.somethingElse as somethingElse
};
Alternatively you could use destructuring for the export of something and somethingElse:
export const { something, somethingElse} = defaults;
And then import it like you did:
import * as mod, { something } from 'moduleA';
But: mod will now contain the props: defaults, something, somethingElse.
If you only wont the default (which equals your defaults):
import mod, { something } from 'moduleA';
You can learn more about the ES6 import and export syntax in Axel Rauschmayr's great blog post:
http://www.2ality.com/2014/09/es6-modules-final.html
import * as mod, { something } from 'moduleA';
The reason something is undefined is because when you: export { defaults as default }; you're exporting a member called default. When you export {apple, banana} you export a member apple and a member banana.
When you import something without specifying the members you want to import you import the member named default. When you do specify the members you wish to import, of course, you import those.
This is why although your code doesn't do what you intend, the following will:
const mod = { something: 'test'};
export { mod as default }; // same as export default mod;
and
import mod, {default as test} from './index'; // test and mod both have the same values
console.log(mod); // { something: 'test' }
console.log(test.something); // test
something is not exported from your module A, only the object defaults is.
So, to get something, you need to take it from what you imported.
import * as mod from 'moduleA';
const something = mod.something;
If you want to be able to import something like this : import {something} from 'moduleA', you will need to export it explicitely. For example:
export const something = {};
const somethingElse = {};
export default const defaults = {
something,
somethingElse
};
I want to re-export a whole module and override only a specific function of the re-exported module. But it seems exporting the override function doesn't get processed when the same function is already re-rexported.
(http://www.ecma-international.org/ecma-262/6.0/#sec-module-semantics-static-semantics-early-errors, 'It is a Syntax Error if the ExportedNames of ModuleItemList contains any duplicate entries.')
The motivation behind my approach is to minimize explicit re-exporting a very big or long module, if I only want to override a specific function or method in the re-exported module.
Is there any way to implement my approach in es6/es2015?
My code so far:
module-a.js
export class MyFirstStandardClass {
sendMeMessages() {
return `hello, I'm a standard implementation`;
}
}
export function talkToMe() {
return `standard talking: how are you doing?`;
}
module-b.js
import * as StandardModule from 'module-a';
export function talkToMe(condition = true) {
if (condition) {
return `project conditional talking: ${StandardModule.talkToMe()}`;
}
return `project without a condition!`;
}
export * from 'module-a';
module-c.js
import * as MyModule from 'module-b';
import React, { Component } from 'react';
export default class App extends Component {
componentWillMount() {
console.log(MyModule);
this.myFirstStandardInstance = new MyModule.MyFirstStandardClass();
}
render() {
return (
<div>
<label>
Class
</label>
<div>
{ this.myFirstStandardInstance.sendMeMessages() }
</div>
<label>
Function
</label>
<div>
{ MyModule.talkToMe(true) } // returns 'standard talking: how are you doing?'; expected 'project conditional talking: standard talking: how are you doing?'
</div>
</div>
);
}
}
It seems my first solution should work. According to the ECMAScript spec local exports should have priority. (http://www.ecma-international.org/ecma-262/6.0/#sec-getexportednames)
It's an issue in the Babel transpiler. More info: https://github.com/systemjs/systemjs/issues/1031#issuecomment-171262430
Issue in Babel: https://phabricator.babeljs.io/T6967
You can select which modules from module-a to export on one line. So in your module-b.js you can do:
// export all modules excluding `talkToMe`
export { MyFirstStandardClass, someOtherModule } from 'module-a';
export function talkToMe(condition = true) {
// ...
}
Or you can export default object and choose what to exclude/override with Object.assign():
import * as StandardModule from 'module-a';
const overridenExports = {
talkToMe: function(condition = true) {
// ...
}
}
const myModule = Object.assign({}, StandardModule, overridenExports);
export default myModule;
and import default like:
import MyModule from 'module-b';
I m actually learning typescript, and I m facing some problems with internal modules.
In fact, I have three files :
index.ts in which I start my app
///<reference path='RouteManager.ts'/>
import RouteManager = RestifyRouting.RouteManager;
var myManager = new RouteManager();
myManager.init("superpath");
RouteManager.ts that manage my REST routes
///<reference path='RouteParser.ts'/>
module RestifyRouting {
export class RouteManager {
routeParser:RouteParser;
constructor() {
}
public init(filePath) {
this.routeParser = new RouteParser();
this.routeParser.register("zfaf","callback");
console.log(filePath);
}
}
}
RouteParser which has to parse some string to get some informations
module RestifyRouting {
export class RouteParser {
constructor() {
}
public register(path, callback) {
console.log('super register');
}
}
}
I have a gulp file that creates my .js and d.ts files and it works great, except for the index.js file. The compiler tells my that RestifyRouting (which is my internal module) is undefined and I dont know why...
Can you help me ?
PS : every files are in the same folder, it's just a learning application.
Thanks for advance
As of TypeScript 1.5 the module syntax is aligned with ES6 module syntax and that is what I have been using as well...
You can remove any references to TypeScript modules and just export the classes directly
index.ts
import { RouteManager } from './RouteManager';
var myManager = new RouteManager();
myManager.init("superpath");
RouteManager.ts
import { RouteParser } from './RouteParser';
export class RouteManager {
routeParser:RouteParser;
constructor() {}
public init(filePath) {
this.routeParser = new RouteParser();
this.routeParser.register("zfaf","callback");
console.log(filePath);
}
}
RouteParser.ts
export class RouteParser {
constructor() {}
public register(path, callback) {
console.log('super register');
}
}
Keeping modules
If you'd like to keep using internal modules then you have to be sure to export your module as well as the classes inside the module.
// RouteManager.ts
export module RestifyRouting {
export class RouteManager{}
}
//index.ts
import { RestifyRouting } from './RouteManager';
//usage
var manager = new RestifyRouting.RouteManager();
Something to keep in mind is that you will not be able to import multiple items into the the same name.
// i.e.
import { RestifyRouting } from './RouteManager';
import { RestifyRouting } from './RouteParser';
NOTES
the {} syntax in the import statement can allow multiple imports
{ Class1, Class2 }
The {} can be skipped if you exporting a default:
//Source (foo.ts):
export default class Foo{}
//Reference:
import Foo from './foo';
//usage:
class User {
foo: Foo;
}