Skip to content

[Design] Syntax to represent module namespace object in dynamic import #14844

Closed

Description

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)) and Promise<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:

  1. Syntax to bring in the dynamic loaded module so compiler can load during compile time
  2. 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)

  1. 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>;
  1. introduce new keyword ,moduleof....when collecting module reference we will also collect from moduleof as well
var p = import(somecondition ? "./MyModule1" : "./MyModule2") as Promise<moduleof "./MyModule1" | moduleof "./MyModule2">;

Proposes for (2) - indicate the return type

  1. 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");
  1. Contextual Type
var p: <Promise<moduleof "./MyModule1" | moduleof "./MyModule2">> = import(somecondition ? "./MyModule1" : "./MyModule2");
  1. Just use casting

  2. 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".

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Assignees

Labels

FixedA PR has been merged for this issueSuggestionAn idea for TypeScript

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions