I made an export Javascript file like following:
export const A = 1;
export const B = 2;
export const C = 3;
And, I try to import that to another Javascript file like following:
import 'path/export_file.js'
console.log(A); // ReferenceError: A is not defined
I know I can fix it if I do the following:
import A from 'path/export_file.js'
// or
import { A, B, C } from 'path/export_file.js'
But I want to use like import 'path/export_file.js'
Some modules just do import'path/file' and I can use all of exported from that module.
What should I do?
Or am I mistaken for something?
There are 2 things to know:
You should know about Import/Export default & named in ES6
As #CertainPerformance's mention, you have to use {} unless the module assigns to global properties.
import { A, B, C } from 'path/export_file.js
In case of mix both Default and Named, you can use * like this
import * as Mix from 'path/export_file.js
Thanks #prosti's answer with a great answer.
Related
Currently i'm trying to get the workitems of my azure devops server with following code:
export function geWorkitems(target: HTMLElement): void {
// Get an instance of the client
let client = WorkitemRestClient.getClient();
client.getWorkItems([1]).then(definitions => {
target.innerText = JSON.stringify(definitions)
}
);
}
show("workitems", geWorkitems);
when I include the needed import its gives me this error:
Import assignment cannot be used when targeting ECMAScript modules. Consider using 'import * as ns from "mod"', 'import {a} from "mod"', 'import d from "mod"', or another module format instead.ts(1202)
The import i am talking about:
import WorkitemRestClient = require("TFS/WorkItemTracking/RestClient");
People have been suggesting to write it this way, but it still doesnt work
import WorkitemRestClient from "TFS/WorkItemTracking/RestClient";
same with import BuildRestClient = require("TFS/Build/RestClient");
Best method
Have you tried the code suggested in the error message (import {a} from "mod"):
import { geWorkitems } from "TFS/WorkItemTracking/RestClient";
Make sure you have the correct spelling and capitalisation because the export name must be the same as the import
Alternative 1
You could also try:
const WorkitemRestClient = require("TFS/WorkItemTracking/RestClient");
using require is like normal assignments so you can't use the import keyword.
require is less used nowadays and works better with the module.exports = {} notation
Alternative 2
Finally, you could keep the second import you mentionne:
import WorkitemRestClient from "TFS/WorkItemTracking/RestClient";
but you need to export it differently with the default keyword:
export default function geWorkitems(target: HTMLElement): void {
Given I have two imports with lots of named exports (too many to write them all out) and I want to reexport these except a few of them. In my case this is because a few exports collide.
As an example of what I want to archive lets assume we have two files:
foo.js:
export const a = 1;
export const b = 2;
bar.js:
export const b = 1;
export const c = 3;
If I want to aggregate and reexport them all using CommonJS I could do something like this:
/* use rest destructuring to put everything except "b" into variable "foo" */
const { b, ...foo } = require("./foo");
const bar = require("./bar");
module.exports = {
...foo,
...bar
};
As I'm using typescript the closest I've gotten is using export = { ... } in a similar way:
import * as foo from "./foo";
import * as bar from "./bar";
const { b, ...foo2 } = foo;
export = {
...foo2,
...bar,
};
However it is my understanding this will create a file with CommonJS module.exports instead of a proper ESM module (and probably require esModuleInterop). And it is a typescript construct and not available when writing vanilla JS.
Is there a way to archive this using ESM import / export instead?
Is there a way to archive this using ESM import / export instead?
No, not in pure standard ESM, not without doing what you're trying to avoid: Listing the named exports. There's no "rest" concept in ESM import/export.
I think you know this, but you could export an object with properties for a, b, and c, but that's a very different thing from re-exporting named exports. It wouldn't be a live binding, and the syntax for importing its parts is different from importing named exports (unless build-time tools like TypeScript or bundlers, etc. are involved).
Just FWIW, here's what that looks like (it's very similar to your TypeScript version near the end), but I don't think it's what you want:
reexport.js:
import * as foo from "./foo.js";
import * as bar from "./bar.js";
const { b, ...restOfFoo } = foo;
export default {
...restOfFoo,
...bar,
};
Then using it is:
// Import the object (which is the default export)
import stuff from "./reexport.js";
// Destructure into local vars (optional, but...)
const { a, b, c } = stuff;
// Use it...
console.log(a, b, c);
That's all standard ESM.
I was wondering and kinda confused as to which style of import should i use, till this moment i came across these imports and i'm not sure which on is faster, or if its worth refactoring my codes to use one of these instead of another one
Type1 :, (very simple, no problem here):
//This is simple and straight forward
import Component from 'Component';
Type2 (This is one of the ones i have some doubt about):
//#definition JavascriptUtils :
export function a {}
export function b {}
///,2000 more lines
Now this can be used in two ways:
//#usage JavascriptUtils :
//1-
import * as JavascriptUtils from 'Utils/JavascriptUtils'
//2-
import {a, b} as JavascriptUtils from 'Utils/JavascriptUtils'
Now i'm not sure if there is a difference between 1 or 2 or if there is, should i even care ?, is there that much difference in performance or package size, i do use this utility a lot, so i'd like to know how much advantage way 1 can give me
Type3:
//#definition UIUtils :
export const UIUtils = {
a,
b,
}
export function a {}
export function b {}
//#usage UIUtils
import {UIUtils} from 'Utils/UIUtils'
Type4:
//#definition UIUtils :
export const UIUtils = {
a,
b,
}
export function a {}
export function b {}
//#definition JSUtils :
export const JSUtils = {
c,
d,
}
export function c {}
export function d {}
//inside utils/index.js
export * from './UIUtils';
export * from './JSUtils';
//#usage UIUtils
import {UIUtils} from 'utils'
import {JSUtils} from 'utils'
So this all the different types of import i used until now, i really like to know which one is the best, which one is faster, which one causes less build size ? or if there is not difference or the difference is small, i'd like to know that as well.
I specially like to know if i'll notice any big difference in build size if i use {a} from import vs * as utils import, my utils are more than 2000 line and are used hundred of times throughout the program
Thanks!
I know that we can import all named modules with alias as below,
import * as name from "module-name";
Ref: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import
Actually, I have re-exported my modules in A.js and the same is inherited in B.js. PFB. Now, it's two level of inheritance, so it's not a big deal to import the named modules. But, when I'm taking this to 5 level of inheritance (A -> B -> C -> D -> E), I need to import all named modules in all files and need to do the (re)export the same in all. Instead of doing this,
Is there any other way to copy scope of all named modules into all level without reiterating the wheel (Import and Export)
Behind the scene of this design is to make them to follow Opps concept and to avoid the redeclaration of the same modules.
A.js
import React from 'react';
import I18n from 'i18n-js';
import m1 from 'module1';
import m2 from 'module2';
export default class A extends React.Component {}
export {React, I18n, m1, m2)
B.js
import BaseComponent from './A';
import {React, I18n, m1, m2) from './A;
export default class B extends A {}
Is there any way to import all named modules without alias like import {*} from './A' (instead of 2nd in B.js)
JavaScript solution:
import * as exports from 'foo';
Object.entries(exports).forEach(([name, exported]) => window[name] = exported);
Note: the imported wrapper object remains there.
Node.js solution:
Object.entries(require('foo')).forEach(([name, exported]) => global[name] = exported);
Is there any way to import all named modules without alias like import {*} from './A' (instead of 2nd in B.js)
No.
And the whole idea of re-exporting more than you need to save the "number of lines" in the final js file as you stated at
Because, It's putting two lines for each import in the final js file. Consider If there are 10 import lines than, 20 lines will be added in final js. When you are thinking for production it will too cost
Does not make much sense, since that's what JS minifiers are for.
To summarise: one should not do that at the very first place:
You export only what you need to export
You import whatever you need wherever you need.
You use JS minifiers to optimise the output JS file size.
Here's a crazy experiment I did, that works, but it's probably dangerous in ways I don't fully understand.
Would somebody explain to me why we don't do this?
var lodash = require("lodash");
function $localizeAll(name) {
return `eval("var " + Object.getOwnPropertyNames(${name}).reduce((code, prop)=>{
if (/^[a-zA-Z$_][a-zA-Z$_0-9]*$/.test(prop)) {
return code.concat(\`\${prop} = ${name}["\${prop}"]\n\`);
} else {
console.warn("did not import '" + prop + "'");
return code;
}
}, []).join(", ")+";")`
}
// this will make all exports from lodash available
eval($localizeAll("lodash"));
console.log(add(indexOf([1,2,6,7,12], 6), 5)); // => 7
It's a bit complicated as it evals in two levels, but it basically iterates of all the properties of an object with the given name in scope and binds all properties that have names qualified to be identifiers to an identifier by that name:
var length = lodash["length"]
, name = lodash["name"]
, arguments = lodash["arguments"]
, caller = lodash["caller"]
, prototype = lodash["prototype"]
, templateSettings = lodash["templateSettings"]
, after = lodash["after"]
, ary = lodash["ary"]
, assign = lodash["assign"]
, assignIn = lodash["assignIn"]
, assignInWith = lodash["assignInWith"]
, assignWith = lodash["assignWith"]
, at = lodash["at"]
, before = lodash["before"]
, bind = lodash["bind"]
, bindAll = lodash["bindAll"]
, bindKey = lodash["bindKey"]
//...
, upperCase = lodash["upperCase"]
, upperFirst = lodash["upperFirst"]
, each = lodash["each"]
, eachRight = lodash["eachRight"]
, first = lodash["first"]
, VERSION = lodash["VERSION"]
, _ = lodash["_"]
;
There are some examples in this list of why this is a bad idea (e.g. it shadows arguments).
You should be able to use this as follows (though you probably shouldn't like they say above).
B.js
import BaseComponent, * as extras from './A';
eval($localizeAll("extras"));
export default class B extends BaseComponent {}
Anyways, couldn't resist trying this out ;)
global is your current scope in node.js, similar to the window object in the browser, so you can import into this object.
To import all symbols from util module:
import * as util from "./util";
util.importAll(util, global);
In util.js:
/**
* Takes all functions/objects from |sourceScope|
* and adds them to |targetScope|.
*/
function importAll(sourceScope, targetScope) {
for (let name in sourceScope) {
targetScope[name] = sourceScope[name];
}
}
... and a number of other functions like assert() etc., which I need everywhere, and which should be part of the JavaScript language, but are not yet. But as others said, use this sparingly.
For Now, there is no clean way to do this.
But you can overcome the problem by :
1) defining an alias
import * as foo from "foo"
2) writing all modules
import {a,b,c,d,...} from "foo"
I came across this source code.
I do not understand the first line:
import type { a, b, c, d } from 'types'
What is the difference with
import { a, b, c, d } from 'types'
Could you please explain? Thanks
import type { a, b, c, d } from 'types'// not sure what it does
import { a, b, c, d } from 'types' // I am familar with this
This is not vanilla JavaScript import usage. This is probably Flow, or a closely-related transpiled language.
I found a blog post from the Flow project entitled Announcing Import Type. I don't know Flow, but it looks like a strictly-type superset of JavaScript. The import type statement is how you import type information about a class without importing the class itself. They give an example where you might want to declare stirctly-typed formal arguments in a function and need to import the appropriate types:
import type {Crayon, Marker} from 'WritingUtensils';
module.exports = function junkDrawer(x: Crayon, y: Marker): void {}
It is importing type definitions from the file.
// Here you are importing the actual method, variable from the file.
import xyz from 'abc';`
// Here you are importing the type defination of xyz
import type { xyz } from 'abc';
Now if you want to use it as
let a: xyz = new xyz();
From MDN, although the missing comas from OP is weird:
Importing defaults: It is possible to have a default export (whether it
is an object, a function, a class, etc.). The import statement may
then be used to import such defaults.
The simplest version directly imports the default:
import myDefault from '/modules/my-module.js';
It is also possible to
use the default syntax with the ones seen above (namespace imports or
named imports). In such cases, the default import will have to be
declared first. For instance:
import myDefault, {foo, bar} from '/modules/my-module.js'; // specific, named imports
In other words, this will import the default as myDefault, and then import the named exports.