New es6 syntax for importing commonjs / amd modules i.e. `import foo = require('foo')`
The correct way is to continue using the old import syntax. The new import syntax is for ES modules only, the old import syntax is for pre-ES6 modules. The two are distinct, intentionally so. import * as foo from 'foo'
imports all the properties of the module 'foo', it does not import the default value as foo
.
From the designer of the feature:
- An export default declaration always declares an exported member named default and is always emitted as an assignment to exports.default. In other words,
export default
consistently has ES module semantics. For compatibility with Babel we could optionally emit an__esModule
marker when a module has a default export, but we wouldn't actually use that marker for anything. - An
export =
declaration, which substitutes a different entity to be exported in place of the module itself, is always emitted as an assignment tomodule.exports
. It is an error to have other exports in a module that usesexport =
. This is the existing TypeScript behavior. - A module that uses
export =
to export another module (be that an internal or external module) can be imported using the new ES6 constructs. In particular, the convenient destructuring imports can be used with such modules. The pattern of usingexport =
to export another module is common in .d.ts files that provide a CommonJS/AMD view of an internal module (e.g. angular.d.ts). - A module that uses
export =
to export a non-module entity in place of the module itself must be imported using the existingimport x = require("foo")
syntax as is the case today.
2016 update: The TypeScript compiler at some point started allowing import * as foo from 'legacy-module-foo'
to get the default import of a legacy module in certain circumstances. This is a violation of the ES6 specification (§15.2.1.16, “The value "*" indicates that the import request is for the target module’s namespace object.”).
When legacy modules you import in this manner are updated to ES6 modules, the “default” imports for those modules will stop working (because * as foo
imports are supposed to be importing namespace objects), which may be extremely confusing if you don’t know that doing this is a TypeScript/SystemJS hack. It is also possible that a future TypeScript realignment to the ES specification will cause them to break.
As such, you should probably prefer to continue to use the legacy import syntax described above to load legacy modules to avoid confusing yourself and other developers working on your code about how ES6 namespace imports work, and to avoid confusing breaking changes.
Using Node.js require vs. ES6 import/export
Update
Since Node v12 (April 2019), support for ES modules is enabled by default, and since Node v15 (October 2020) it's stable (see here). Files including node modules must either end in .mjs
or the nearest package.json
file must contain "type": "module"
. The Node documentation has a ton more information, also about interop between CommonJS and ES modules.
Performance-wise there is always the chance that newer features are not as well optimized as existing features. However, since module files are only evaluated once, the performance aspect can probably be ignored. In the end you have to run benchmarks to get a definite answer anyway.
ES modules can be loaded dynamically via the import()
function. Unlike require
, this returns a promise.
Previous answer
Are there any performance benefits to using one over the other?
Keep in mind that there is no JavaScript engine yet that natively supports ES6 modules. You said yourself that you are using Babel. Babel converts import
and export
declaration to CommonJS (require
/module.exports
) by default anyway. So even if you use ES6 module syntax, you will be using CommonJS under the hood if you run the code in Node.
There are technical differences between CommonJS and ES6 modules, e.g. CommonJS allows you to load modules dynamically. ES6 doesn't allow this, but there is an API in development for that.
Since ES6 modules are part of the standard, I would use them.
How to use es6 import for importing electron instead of require function
It seems that you are missing a module resolution setting used by Ts compiler.
You can add a tsconfig.json
file in your project root containing a compilerOptions.module
value:
{
"compilerOptions": {
"module": "es2015"
}
}
See Typescript documentation for further details.
What is the most forwards-compatible way of importing CommonJS from TypeScript?
const foo = require("foo")
This one is the worst one, foo
will be typed as any, I would avoid it at all cost
import foo = require("foo")
This is typescript specific import syntax, and again should be avoided as much as possible. At runtime it is compiled to var foo = require("foo")
, but at compile time it offers type safety. It is the only way to import a module that uses export assignment.
import * as foo from "foo"
This is the official ES2015 syntax and should be favored whenever possible (except for the export assignment case I think it can be used in all other cases).
If you compile to commonjs
the above syntax will still be transpiled as const foo = require("./foo");
at runtime so it should behave in the same way.
There is one caveat to this, typescript will not emit imports that are unused and import that are only used for their types (read here) so if you want to import a module for side effects you can use this syntax:
import "foo"
ES6 module syntax for multiple static functions
are you perhaps looking for the wildcard?
import * as nums from '../utils/numbers';
A similiar question: TypeScript 1.5: ES6 Module default import of CommonJS 'export =' (.d.ts only issue?)
A more detailed answer into this: New es6 syntax for importing commonjs / amd modules i.e. `import foo = require('foo')`
TypeScript import/as vs import/require?
These are mostly equivalent, but import *
has some restrictions that import ... = require
doesn't.
import * as
creates an identifier that is a module object, emphasis on object. According to the ES6 spec, this object is never callable or new
able - it only has properties. If you're trying to import a function or class, you should use
import express = require('express');
or (depending on your module loader)
import express from 'express';
Attempting to use import * as express
and then invoking express()
is always illegal according to the ES6 spec. In some runtime+transpilation environments this might happen to work anyway, but it might break at any point in the future without warning, which will make you sad.
TypeScript 1.5: ES6 Module default import of CommonJS 'export =' (.d.ts only issue?)
The syntax you are looking for
import * as moment from "moment";
Related Topics
What Is This JavaScript Pattern Called and Why Is It Used
How to Link Each User to Their Data in Firebase
When and Why to 'Return False' in JavaScript
Does Never Resolved Promise Cause Memory Leak
Escaping Strings in JavaScript
How to Use React Hooks in React Classic 'Class' Component
Programmatically Open New Pages on Tabs
Window.Onbeforeunload Ajax Request in Chrome
One Liner to Flatten Nested Object
Disable Submit Button on Form Submit
Adding 'Click' Event Listeners in Loop
How to Access a Numeric Property
Firebase: Setting Additional User Properties
Why Does Array.Prototype.Push Return the New Length Instead of Something More Useful