-
Notifications
You must be signed in to change notification settings - Fork 0
Modules documentation #1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
modules/02_Theory.md
Outdated
4. What kind of module is the file resolved by that lookup? | ||
5. Does the module system allow the kind of module detected in (1) to reference the kind of module detected in (4) with the syntax decided in (2)? | ||
6. Once the `"greetings"` module has been analyzed, what piece of that module is bound to `sayHello`? | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think at this point we want to reflect on the runtime execution of this code, specifically as relates to the resolution of module specifiers as an abstract operation. This gives a good to define "host" and "module resolution" in an agnostic way and lets the following paragraph have fewer embedded definitions.
modules/02_Theory.md
Outdated
|
||
1. to compile files into a valid **output module format**, | ||
2. to ensure that imports in those **outputs** will **resolve successfully**, and | ||
3. to know what **type** to assign to **imported names**. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure if it bears mention in this section or not, but there's also a need for an understanding of what module names are permitted in what contexts (i.e. "reverse" module resolution, beyond just what auto-import needs). This is the crux of the "Cannot be named / likely not portable" error.
modules/02_Theory.md
Outdated
Before we move on, it’s worth making sure we’re on the same page about the term _host_, because it will come up frequently. We defined it before as “the system that ultimately consumes the output code to direct its module loading behavior.” In other words, it’s the system outside of TypeScript that TypeScript’s module analysis tries to model: | ||
|
||
- When the output code (whether produced by `tsc` or a third-party transpiler) is run directly in a runtime like Node, the runtime is the host. | ||
- When there is no “output code” because a runtime consumes TypeScript files directly, the runtime is still the host. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- When there is no “output code” because a runtime consumes TypeScript files directly, the runtime is still the host. | |
- When there is no “output code” because a runtime consumes TypeScript files directly (e.g. `ts-node`, deno, bun), the runtime is still the host. |
modules/02_Theory.md
Outdated
- When there is no “output code” because a runtime consumes TypeScript files directly, the runtime is still the host. | ||
- When a bundler consumes TypeScript inputs or outputs and produces a bundle, the bundler is the host, because it looked at the original set of imports/requires, looked up what files they referenced, and produced a new file or set of files where the original imports and requires are erased or transformed beyond recognition. (That bundle itself might comprise modules, and the runtime that runs it will be its host, but TypeScript doesn’t know about anything that happens post-bundler.) | ||
- If another transpiler, optimizer, or formatter runs on TypeScript’s outputs, it’s _not_ a host that TypeScript cares about, as long as it leaves the imports and exports it sees alone. | ||
- When loading modules in a web browser, the behaviors TypeScript needs to model are actually split between the web server and the module system running in the browser. The browser’s JavaScript engine (or a script-based module-loading framework like RequireJS) controls what module formats are accepted, while the web server decides what file to send when one module triggers a request to load another. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe a reminder that module specifier are not URLs and URLS are not file specifiers
Co-authored-by: Ryan Cavanaugh <[email protected]>
just randomly and accidentally found this repo and this pr and got surprised with the great amount of interesting and useful information about typescript modules. what is this for? |
This was just an easy place for me to push WIP content and share it with the team. It’s PR’d at microsoft/TypeScript-Website#2946 now. |
"noEmit": true, // or `emitDeclarationOnly` | ||
"allowImportingTsExtensions": true, | ||
"allowArbitraryExtensions": true, | ||
"verbatimModuleSyntax": true, // or `isolatedModules` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would consider IM "soft deprecated" in favor of VMS, so maybe worth downplaying
</html> | ||
``` | ||
|
||
This approach had some downsides, especially as web pages grew larger and more complex. In particular, all scripts loaded onto the same page share the same scope—appropriately called the “global scope”—meaning the scripts had to be very careful not to overwrite each others’ variables and functions. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We might need to define "scope" more explicitly; not sure
import sayHello from "greetings"; | ||
sayHello("world"); | ||
``` | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This section is good but sort of puts the cart before the horse. We can start with "At runtime, something will happen" (via all these same steps described in checking), then describe TS's job in terms of asking questions about what that behavior is.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm, that’s a good point, but this is supposed to be .ts
file contents, so it’s hard to say what’s going to happen at runtime without presupposing what module format we’re going to emit. But maybe it can be stated abstractly enough to gloss over the potential ESM/CJS differences here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The updated version of this section was rewritten to account for the possibility of a runtime that may load the TS file directly, which further complicates prefacing this with a discussion of what the runtime will do 🤔
- [**`es2022`**](./03_Reference.md#es2015-es2020-es2022-esnext): Adds support for top-level `await` to `es2020`. | ||
- [**`esnext`**](./03_Reference.md#es2015-es2020-es2022-esnext): Currently identical to `es2022`, but will be a moving target reflecting the latest ECMAScript specifications, as well as module-related Stage 3+ proposals that are expected to be included in upcoming specification versions. | ||
- **[`commonjs`](./03_Reference.md#commonjs), [`system`](./03_Reference.md#system), [`amd`](./03_Reference.md#amd), and [`umd`](./03_Reference.md#umd)**: Each emits everything in the non-standard module system named, and assumes everything can be successfully imported into that module system. These are no longer recommended for new projects and will not be covered by this documentation. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"none"
> | ||
> The upside of this “author ESM, output anything” strategy was that TypeScript could use standard JavaScript syntax, making the authoring experience familiar to newcomers, and (theoretically) making it easy for projects to start targeting ESM outputs in the future. There are three significant downsides, which became fully apparent only after ESM and CJS modules were allowed to coexist and interoperate in Node.js: | ||
> | ||
> 1. Early assumptions about how ESM/CJS interoperability would work in Node.js were wrong, and today, interoperability rules differ between Node.js and bundlers. Consequently, the configuration space for modules in TypeScript is large. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
> 1. Early assumptions about how ESM/CJS interoperability would work in Node.js were wrong, and today, interoperability rules differ between Node.js and bundlers. Consequently, the configuration space for modules in TypeScript is large. | |
> 1. Early assumptions about how ESM/CJS interoperability would work in Node.js turned out to be wrong, and today, interoperability rules differ between Node.js and bundlers. Consequently, the configuration space for modules in TypeScript is large. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I left some comments but take them as suggestions, not requirements.
I read ESM-CJS-interop and it's flawless, no notes.
Closing since microsoft/TypeScript-Website#2946 is now the canonical state of in-progress work |
No description provided.