Description
import(specifier)
is a newly proposed syntax for dynamically module loading. import(specifier)
takes an assignment expression as an input (Note: unlike ES6 static import which only allow string literal as module specifier) and returns a promise of module namespace object.
The full proposal can be found here
Original issue: #12364
This issue will discuss design proposal for implementing import()
: parsing, type-checking, and emitting.
The proposal will NOT include "module namespace object" type and expressing the shape of the loaded module (To be able to express such type will allow users to cast the result instead of "any" to be what they expected at runtime)...The issue will be discussed and implemented separately.
Parsing
import(specifier)
will be parsed as CallExpression. and specifier
will be parsed as AssignmentExpression
Error
-
Error if the
module
flag is ES2015. -
Error if
specifier
is not assignable to string type
Type-checking
-
specifier
is type checked as string type. (Clarification: the only limitation forspecifier
in original proposal is that it can calledtoString()
) -
The return of
import(specifier)
will be as following
-- if known module can be resolved fromspecifier
, then we return Promise of module namespace object
-- if not known module, then we return Promise of any.This will give an error inAfter offline discussion with @mhegazy @bowdenk7 @DanielRosenwasser, we think reporting an error without providing a way to easily get out of it (see [Design] Syntax to represent module namespace object in dynamic import #14844 for more detail) is undesirable. By casting tonoImplicitAny
mode andimport()
is used as an expressionPromise<any>
to satisfy the compiler will not provide users any benefit and arguably is a drawback because if in the future, there is a way to type the module easily, upgrading to use such syntax will not be convenient. Therefore, we will not issue annoImplicitAny
error with this feature but with [Design] Syntax to represent module namespace object in dynamic import #14844 instead. -
We will use existed module resolution logic to try to figure out the module of the dynamic import.
Emit
Emit for each different module
kind emit is outlined below
import('blah');
- Node
Promise.resolve().then(() => require('blah'));
- AMD
define(["require", "exports"], function (require, exports) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
new Promise(resolve => require(['blah'], resolve));
});
- UMD
(function (factory) {
if (typeof module === "object" && typeof module.exports === "object") {
var v = factory(require, exports);
if (v !== undefined) module.exports = v;
}
else if (typeof define === "function" && define.amd) {
define(["require", "exports"], factory);
}
})(function (require, exports) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
require.length === 1 ?
/*CommonJs Require*/ Promise.resolve().then(() => require('blah'));
/*Amd Require*/ new Promise(resolve => require(['blah'], resolve));
});
- System (Updated from comment)
System.register([], function (_export, _context) {
return {
setters: [],
execute: () => {
_context.import('dynamic');
}
};
});
- ES2018 new value
import('blah')