ES6: import specific values with namespace - ecmascript-6

There is a specific thing i want to do from time to time, that i cannot figure out:
suppose module1.js exports 3 values:
//module1.js
export const a = 'a';
export const b = 'b';
export const c = 'c';
And then, in module2.js, I want to import two of these, into an object (as a kind of namespace thing):
//module2.js
import { a, c } as constants from './module1'; //<-WRONG!
So what I end up doing is something like this:
//module2.js
import { a, c } from './module1';
const constants = { a, c };
This works, but now a and c exist both in constants and also directly in the module scope.
Is there a way to avoid this?

As per MDN documentation, you can either set an alias on entire module contents such as * as constants or a single content such as b as constants. But you can't set an alias on specific contents. So one of the solutions would be using *.
import * as constants from './module1';
Another possible solution would be passing { a, c } as default.
//module1.js
export const a = ...
export const b = ...
export const c = ...
export const d = ...
export default { a, b, c };
/module2.js
import contants from './someModule';
doStuff(constatns);
Lastly, If you don't want to pass these constants as default, you can create an object and pass that object.
//module1.js
export const a = ...
export const b = ...
export const c = ...
export const b = ...
export const myCustomConstants = { a, c };
//module2.js
import { myCustomConstants } from './someModule';
doStuff(myCustomConstants);

Do you mean something like
import * as constants from './module1';
You could also remove some if you need to pass them down, something like lodash pick
const cleanConstants = _.pick(['a', 'c'], constants);

Related

ES6 destructuring with expression [duplicate]

This works…
const { prop1:val1, prop2:val2 ) = req.query
val1 = val1.toLowerCase()
Though, I'm more inclined to do something like
const { prop1.toLowerCase():val1, prop2:val2 } = req.query
or
const { prop1:val1.toLowerCase(), prop2:val2 } = req.query
neither of which work. Is there a syntax similar to this or must manipulations be done outside of the destructing assignment?
No, this is not possible. A destructuring assignment does only assign, it does not do arbitrary transformations on the value. (Setters are an exception, but they would only complicate this).
I would recommend to write
const { prop1, prop2:val2 ) = req.query;
const val1 = prop1.toLowerCase();
or, in one statement:
const { prop1, prop2:val2 ) = req.query, val1 = prop1.toLowerCase();
The trouble with the temporary variable solutions is that they introduce different versions of the same data into the scope, which can lead to bugs.
This solution creates a utility function that receives the object to be destructured as well as a second object that is a mapping of property names to transformation functions. It's a little more verbose, but does the trick.
// Utility functions to perform specified transformations on an object
function transformProps(obj, trans) {
return Object.assign({}, obj, ...Object.entries(trans).map(([prop, fn]) =>
prop in obj ? {[prop]: fn(obj[prop])} : null
));
}
const { prop1:val1, prop2:val2 } = transformProps(
{prop1: "FOO", prop2: "BAR"},
{prop1: v => v.toLowerCase()} // Transformations to be made
);
console.log(val1, val2);

ES6 modules export and import

foo.js
const a = 1
const b = 2
const c = 3
let d = 4
export default { a, b }
export { c }
export d
What's the difference between exported a, b, c, d?
And how to import them correctly?
Does the Babel compilation will effect it?
You can only export declarations (except for the default export) that means that:
export d;
is invalid, it has to be:
export const d = 1;
And how to import them correctly?
import main, { c, d } from "sth";
const {a, b} = main;
You can import c and d in the same way, only the object properties a and b can't be accesed directly as you can't destructure objects inside the import statement, therefore you have to destructure them in a new line which is just ugly. To quote Bergi: "Don't do that", instead go with c or d.

Object from array using es6

I would like to have this object:
const m = {a:undefined, b:undefined, d:undefined};
but would prefer to produce it from an array:
const m = {}
const l = ["a","b","c"];
for (const i in l){
m[l[i]] = undefined;
}
But what would be a nicer way of doing this when using es6?
You could use for/of, but Array#reduce (which exists since ES5) might be more elegant:
const m = ['a', 'b', 'c'].reduce((o, k) => (o[k] = undefined, o), {});
However, if you need this a lot, I'd recommend to create a reusable function with a proper name.
You can Array#map each property to an object, and combine them using the spread syntax, and Object#assign:
const m = Object.assign(...['a', 'b', 'c'].map((prop) => ({ [prop]: undefined })));
console.log(m);

es6 export of a function doesn't work

I want my module to export multiple functions and numerical constants.
When I import all exported properties of my module I see that functions are not actually imported.
//module1.js
const func1 = (a) => {console.log(1)};
const func2 = (b) => {console.log(2)};
const variable1 = 1;
const variable2 = 2;
export const exp1 = func1;
export const exp2 = func2;
export const exp3 = variable1;
export const exp4 = variable2;
.
//anotherFile.js
import * as module1 from './module1';
console.log(JSON.stringify(module1, null, 2)); // {"module1": {"exp3":1, "exp4":2}}
What is the correct way of importing functions?
All works!
my problem was in console.log(JSON.stringify(module1, null, 2));
JSON.stringify was cutting off my functions

Does TypeScript support namespace?

As in the title: does TypeScript support namespaces? If so, how do I use them?
Typescript allows to define modules closely related to what will be in ECMAScript 6. The following example is taken from the spec:
module outer {
var local = 1;
export var a = local;
export module inner {
export var x = 10;
}
}
As you can see, modules have names and can be nested. If you use dots in module names, typescript will compile this to nested modules as follows:
module A.B.C {
export var x = 1;
}
This is equal to
module A {
module B {
module C {
export var x = 1;
}
}
}
What's also important is that if you reuse the exact same module name in one typescript program, the code will belong to the same module. Hence, you can use nested modules to implement hierarchichal namespaces.
As of version 1.5, Typescript supports namespace keyword. Namespaces are equivalent to internal modules.
From What's new in Typescript:
Before:
module Math {
export function add(x, y) { ... }
}
After:
namespace Math {
export function add(x, y) { ... }
}
For defining an internal module, now you can use both module and namespace.
Here is a TypeScript namespace example:
///<reference path='AnotherNamespace/ClassOne.ts'/>
///<reference path='AnotherNamespace/ClassTwo.ts'/>
module MyNamespace
{
import ClassOne = AnotherNamespace.ClassOne;
import ClassTwo = AnotherNamespace.ClassTwo;
export class Main
{
private _classOne:ClassOne;
private _classTwo:ClassTwo;
constructor()
{
this._classOne = new ClassOne();
this._classTwo = new ClassTwo();
}
}
}
There is no 'namespace' keyword, but internal modules (using the 'module' keyword) and external modules (using the 'export' keyword) offer a similar way to partition your code into logical hierarchies.
False...
module A.B.C {
export var x = 1;
}
is equal to
module A {
export module B {
export module C {
export var x = 1;
}
}
}
because you can write outside the module A :
var y = A.B.C.x;
But :
module A {
module B {
module C {
export var x = 1;
}
var y = C.x; // OK
}
//var y = B.C.x; // Invalid
}
//var y = A.B.C.x; // Invalid