I am running a react application. The code below does not work because of the following error message:
import = is not supported by #babel/plugin-transform-typescript
Please consider using import <moduleName> from '<moduleName>'; alongside Typescript's --allowSyntheticDefaultImports option.
apiTypes.d.ts
declare module ModuleA {
declare module ModuleB {
export interface ModuleABInterface {
}
}
}
token.ts
import ModuleABInterface = ModuleA.ModuleB.ModuleABInterface
let test: ModuleABInterface
What would be the correct solution to import from nested modules?
It's impossible to nest ES6 modules. TypeScript namespaces (that were originally called "modules") can be nested, but should be avoided. And yes, it's impossible to import from them - you can only import the namespace object itself, using normal ES6 import declarations (not the deprecated import = syntax), then access their properties.
const csv = require('csvtojson') this works
import { csv } from 'csvtojson' but this dont.
Can anyone help what the issue here ?
The {} is to import partially from the csvtojson lib, and require is used to import every exported object from lib.
What kind of error do you get? Could it be that later in your code you depend on something else from csvtojson and that is why you get an error.
Consider the example below:
// hello.js
function hello1() {
return 'hello1'
}
function hello2() {
return 'hello2'
}
export { hello1, hello2 }
// app.js
import { hello1, hello2 } from './hello'
hello1() // returns hello1
hello2() // returns hello2
You would have to use .mjs file extention instead of .js.
Read about ECMAScript modules enabling - it is still experimental so you may want to be sure before using it.
Another way would be to use babel to compile code to commonJS
tealium-tracker is written in es6 and transpiled using Babel before published to npm.
When consumers do:
import initTealiumTracker from "tealium-tracker";
everything works as expected.
However, some consumers want to use a require instead of an import, and have to append .default:
const initTealiumTracker = require("tealium-tracker).default;
How could I publish the library to avoid appending .default?
I want consumers to be able to do either:
import initTealiumTracker from "tealium-tracker";
or
const initTealiumTracker = require("tealium-tracker);
Source code
In your source code, If you are ok with using commonJS syntax for import and export...
One option would be to replace all import and export with require and module.exports. Looks like webpack doesn't allow mixing the syntaxes (ES6 and commonJS modules).
So your index.js file can require the functions from dependent module as
const { callUtag, flushUtagQueue } = require("./utagCaller");
and export the default function as
module.exports = initTealiumTracker;
module.exports.default = initTealiumTracker;
Likewise your dependent module can export the functions as
module.exports = { callUtag, flushUtagQueue };
This way, consumers should be able to use either
import initTealiumTracker2 from "tealium-tracker";
OR
const initTealiumTracker1 = require("tealium-tracker");
I want to be able to access all exports of a module without having to say module. before the export.
Let's say that I have a module:
// mymod.js
module.exports.foo = function() {
console.log("foo!");
}
module.exports.bar = "bar!";
And a main file:
// main.js
var mymod = require("./mymod.js");
mymod.foo();
Is there a way to call foo() without needing to say mymod. before? This can be achieved in python by saying import module as *.
What is the NodeJS equivalent to this?
In ES6 you can import modules in the following ways
import moduleName from "path/to/module"; // import default export from the file as moduleName object, moduleName can be anything
import { exportMemberName1, exportMemberName2, ... } from "path/to/module"; // destructured import, it will destructure import and can access the export module without prefixing anything
import * as moduleName from "path/to/module"; // import everything exported from the file as moduleName object, you can access every export members from that object, moduleName can be anything
These are the only methods provided by ES6 to import module (you can also use require).
If you have to import 100s of modules best ways is first method, import everything as an object and destructure on the go, I meant if you have lots of functions or methods, destructure what you want in that function in side that function, eg.
import * as moduleName from "path/to/file";
function function1(){
const { exportMember1, exportMember2 } = module;
}
function function2(){
const { exportMember1, exportMember5, exportMember7 } = module;
}
I want to be able to access all exports of a module without having to
say module. before the export.
Use the shorthand:
exports.myVar = myVar
exports.foo = () => {}
Or use an Object:
module.exports = {
foo,
myVar
}
// main.js
var mymod = require("./mymod.js");
mymod.foo();
Is there a way to call foo() without needing to say mymod. before?
This can be achieved in python by saying import module as *. What is
the NodeJS equivalent to this?
Use destructuring:
const { foo } = require("./mymod.js")
lets say that I have 100 exports in a file. Do I need to put commas
after every import inside the { }? There must be a better way to do
this
If you have 100 exports why would you want to import them all globally as their own functions? myMod.func is better for clarity.
A hacky workaround might be to do const myMod = require('myMod') then map it putting the functions on the global object. Or put them on the global from the start instead of exporting it.
You can use ES6 destructuring:
var { foo } = require("./mymod.js");
foo();
I have a situation where a I have a tiny-but-not-that-tiny generic utilities that is used along a couple of modules (all it's functions are used), in which there is a decent amount of modules already loaded. This functions are obviously named in a way you know there are a part of a generic utilities modules, so the "module.function" it's redundant, does not improve the readeability of the code. So, I prefered to mimick the "import * from module" of Python. Note that this is the first time I come across this situation, therefore, IMO, this mechanism, in almost every case, is not a good practice at all. The only way to do that, is iterating over the exports of the module, and adding the functions to the global object. I made a function to make the intention clear.
const importAll = () => {
return {
mod: null,
from(modName) {
this.mod = require(modName);
Object.keys(this.mod)
.forEach(exportedElementId => global[exportedElementId] = this.mod[exportedElementId]);
}
}
}
And it is used like this:
importAll().from('module-name');
Note that this only works if the module exports an object. Wont work if the module exports, for example, an array.
Here is another way, which may be a bit cleaner and more convenient in some cases: method importAll() is implemented inside export-heavy module, so it might be called immediately after require(), making this call very brief.
This works really well for large modules stuffed with simple standard functions and constants that are used across multiple projects.
Example:
// module.js
'use strict';
function func1() { return '4'; };
function func2() { return 2; };
function importAll() { delete this.importAll; Object.assign(global, this); };
module.exports = { func1, func2, importAll };
Then, in the main app, module can be unwrapped as follows:
// app.js
'use strict';
require('./module').importAll();
console.log("result: '%d'", func1() + func2());
There are few caveats though:
since properties/methods are added to global object, those might override some existing properties/methods, so be careful with naming.
those properties/methods will become available EVERYWHERE: in all modules, sub-modules, etc, so no need to call require() more than once.
In node, I can define a module like this by setting the properties of exports object :
module.js
exports.fun = function (val) {
console.log(val);
};
and the ask for it using var module = require('module') in and the use the module.fun() function.
Is it possible to define the module in TypeScript like this:
module.ts
exports.fun = function (val :string) {
console.log(val);
};
and then import the module in some other file using node like syntax, say, import module = require('module.ts') so that it compiles to nodejs but, if now I use module.fun() in some .ts file, it should give me an error if the arguments don't match the type specified in module.ts file.
How can I do this in Typescript?
Yes it is possible to use the true js syntax. You are receiving the error since you are using the import keyword which expects the imported file to use the export keyword. If you want the js exports.foo syntax you should use var instead of import. The following will compile/work just fine:
var module = require('module.ts')
What you've described basically exactly how external modules in TypeScript work.
For example:
Animals.ts
export class Animal {
constructor(public name: string) { }
}
export function somethingElse() { /* etc */ }
Zoo.ts
import a = require('./Animals');
var lion = new a.Animal('Lion'); // Typechecked
console.log(lion.name);
Compile with --module commonjs and run zoo.js in node.