Description
openedon Mar 24, 2017
Another half of dynamic import #14774 is to enable users to be able to describe the shape of the module namespace object return by dynamic import. This is needed because
-
TypeScript currently can only resolve module if the specifier is a string literal (recall syntax of dynamic import
import(specifier)
) andPromise<any>
will be returned...Therefore we need a way for users to be able to specify the module shape in type argument of the Promise and escape noImplicitAny (Note if dynamic import is used as expression statement. we won't issue noImplicitAny) -
When we emit declaration file, we need a syntax to indicate that this is a
Promise of some module
. Currently compiler will give an error as reference external module is not the same as the module of containing file (or lack of one)
🚲 🏠 There are two ares which need to be discuss:
- Syntax to bring in the dynamic loaded module so compiler can load during compile time
- Syntax to specifier the return value of dynamic load (e.g just as a cast, or type argument to dynamic import etc.)
Proposes for (1) - bring in the module (This assume that we will use casting syntax but it doesn't have)
- use namespace import, (this will get elided anyway if just used as type)
import * as MyModule1 from "./MyModule1"
import * as MyModule12 from "./MyModule2"
var p = import(somecondition ? "./MyModule1" : "./MyModule2") as Promise<typeof MyModule1 | typeof MyModule2>;
- introduce new keyword ,
moduleof
....when collecting module reference we will also collect frommoduleof
as well
var p = import(somecondition ? "./MyModule1" : "./MyModule2") as Promise<moduleof "./MyModule1" | moduleof "./MyModule2">;
Proposes for (2) - indicate the return type
- Since dynamic import is parsed as call expression, we can reused the mechanism of specifying type argument
var p = import<Promise<moduleof "./MyModule1" | moduleof "./MyModule2">>(somecondition ? "./MyModule1" : "./MyModule2");
- Contextual Type
var p: <Promise<moduleof "./MyModule1" | moduleof "./MyModule2">> = import(somecondition ? "./MyModule1" : "./MyModule2");
-
Just use casting
-
allow all of the above.
Design meeting update #14853
In addition to be able to simply refer to shape of module namespace object, it is also desirable to use as a QualifiedName
(e.g var x: <some syntax to indicate that we refer to module object>.namespace.interface
) and to have syntax that can easily allow users to be able to do so is crucial.
Candidates we are currently considered:
declare var m: module("./foo").namespace.Interface // this one seems to be the most popular
declare var m: (moduleof "./module").namespace.Interface;
declare var m: (importof "./module").namespace.Interface;
declare var m: (module "./module").namespace.Interface;
I will want to discuss some performance/incremental parsing related to this area and see if we think it will be desirable to consider top-level type import like import type * as ns from "./a.js".