New Es6 Syntax for Importing Commonjs/Amd Modules I.E. 'Import Foo = Require('Foo')'

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 to module.exports. It is an error to have other exports in a module that uses export =. 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 using export = 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 existing import 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 newable - 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



Leave a reply



Submit