Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ declare module "*.html" {

This section discusses the details of each `module` compiler option value. See the [_Module output format_](/docs/handbook/modules/theory.html#the-module-output-format) theory section for more background on what the option is and how it fits into the overall compilation process. In brief, the `module` compiler option was historically only used to control the output module format of emitted JavaScript files. The more recent `node16`, `node18`, and `nodenext` values, however, describe a wide range of characteristics of Node.js’s module system, including what module formats are supported, how the module format of each file is determined, and how different module formats interoperate.

### `node16`, `node18`, `nodenext`
### `node16`, `node18`, `node20`, `nodenext`

Node.js supports both CommonJS and ECMAScript modules, with specific rules for which format each file can be and how the two formats are allowed to interoperate. `node16`, `node18`, and `nodenext` describe the full range of behavior for Node.js’s dual-format module system, and **emit files in either CommonJS or ESM format**. This is different from every other `module` option, which are runtime-agnostic and force all output files into a single format, leaving it to the user to ensure the output is valid for their runtime.

Expand Down
2 changes: 1 addition & 1 deletion packages/documentation/copy/en/modules-reference/Theory.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ The `module` compiler option provides this information to the compiler. Its prim

The available `module` settings are

- [**`node16`**](/docs/handbook/modules/reference.html#node16-node18-nodenext): Reflects the module system of Node.js v16+, which supports ES modules and CJS modules side-by-side with particular interoperability and detection rules.
- [**`node16`**](/docs/handbook/modules/reference.html#node16-node18-node20-nodenext): Reflects the module system of Node.js v16+, which supports ES modules and CJS modules side-by-side with particular interoperability and detection rules.
- [**`node18`**](/docs/handbook/modules/reference.html#node16-node18-nodenext): Reflects the module system of Node.js v18+, which adds support for import attributes.
- [**`nodenext`**](/docs/handbook/modules/reference.html#node16-node18-nodenext): A moving target reflecting the latest Node.js versions as Node.js’s module system evolves. As of TypeScript 5.8, `nodenext` supports `require` of ECMAScript modules.
- [**`es2015`**](/docs/handbook/modules/reference.html#es2015-es2020-es2022-esnext): Reflects the ES2015 language specification for JavaScript modules (the version that first introduced `import` and `export` to the language).
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -868,7 +868,7 @@ tsc app.ts util.ts --target esnext --outfile index.js
<td><code><a href='/tsconfig/#moduleResolution'>--moduleResolution</a></code></td>
<td><p><code>classic</code>, <code>node10</code>/<code>node</code>, <code>node16</code>, <code>nodenext</code>, or <code>bundler</code></p>
</td>
<td><p><code>Node10</code> if <a href="#module"><code>module</code></a> is <code>CommonJS</code>; <code>Node16</code> if <a href="#module"><code>module</code></a> is <code>Node16</code> or <code>Node18</code>; <code>NodeNext</code> if <a href="#module"><code>module</code></a> is <code>NodeNext</code>; <code>Bundler</code> if <a href="#module"><code>module</code></a> is <code>Preserve</code>; <code>Classic</code> otherwise.</p>
<td><p><code>Node10</code> if <a href="#module"><code>module</code></a> is <code>CommonJS</code>; <code>Node16</code> if <a href="#module"><code>module</code></a> is <code>Node16</code> or <code>Node18</code>; <code>Node20</code> if <a href="#module"><code>module</code></a> is <code>Node20</code>; <code>NodeNext</code> if <a href="#module"><code>module</code></a> is <code>NodeNext</code>; <code>Bundler</code> if <a href="#module"><code>module</code></a> is <code>Preserve</code>; <code>Classic</code> otherwise.</p>
</td>
</tr>
<tr class="option-description even"><td colspan="3">
Expand Down Expand Up @@ -1462,7 +1462,7 @@ tsc app.ts util.ts --target esnext --outfile index.js
<td><code><a href='/tsconfig/#target'>--target</a></code></td>
<td><p><code>es3</code>, <code>es5</code>, <code>es6</code>/<code>es2015</code>, <code>es2016</code>, <code>es2017</code>, <code>es2018</code>, <code>es2019</code>, <code>es2020</code>, <code>es2021</code>, <code>es2022</code>, <code>es2023</code>, <code>es2024</code>, or <code>esnext</code></p>
</td>
<td><p><code>ES5</code></p>
<td><p><code>es2023</code> if <a href="#module"><code>module</code></a> is <code>node20</code>; <code>esnext</code> if <a href="#module"><code>module</code></a> is <code>nodenext</code>; <code>ES5</code> otherwise.</p>
</td>
</tr>
<tr class="option-description even"><td colspan="3">
Expand Down
7 changes: 4 additions & 3 deletions packages/tsconfig-reference/copy/en/options/module.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,13 +87,14 @@ export const twoPi = valueOfPi * 2;

In addition to the base functionality of `ES2015`/`ES6`, `ES2020` adds support for [dynamic `import`s](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/import), and [`import.meta`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/import.meta) while `ES2022` further adds support for [top level `await`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await#top_level_await).

#### `node16`/`node18`/`nodenext`
#### `node16`/`node18`/`node20`/`nodenext`

The `node16`, `node18`, and `nodenext` modes integrate with Node's [native ECMAScript Module support](https://nodejs.org/api/esm.html). The emitted JavaScript uses either `CommonJS` or `ES2020` output depending on the file extension and the value of the `type` setting in the nearest `package.json`. Module resolution also works differently. You can learn more in the [handbook](/docs/handbook/esm-node.html) and [Modules Reference](/docs/handbook/modules/reference.html#node16-node18-nodenext).
The `node16`, `node18`, `node20`, and `nodenext` modes integrate with Node's [native ECMAScript Module support](https://nodejs.org/api/esm.html). The emitted JavaScript uses either `CommonJS` or `ES2020` output depending on the file extension and the value of the `type` setting in the nearest `package.json`. Module resolution also works differently. You can learn more in the [handbook](/docs/handbook/esm-node.html) and [Modules Reference](/docs/handbook/modules/reference.html#node16-node18-nodenext).

- `node16` is available from TypeScript 4.7
- `node18` is available from TypeScript 5.8 as a replacement for `node16`, with added support for import attributes.
- `nodenext` is available from TypeScript 4.7, but its behavior changes with the latest stable versions of Node.js. As of TypeScript 5.8, `nodenext` supports `require` of ECMAScript modules.
- `node20` is available from TypeScript 5.9 and provides a stable option intended to model the behavior of Node.js v20. Unlike `nodenext`, this option is unlikely to have new behaviors in the future. Also unlike `nodenext`, specifying `--module node20` will imply `--target es2023` unless otherwise configured.
- `nodenext` is available from TypeScript 4.7, but its behavior changes with the latest stable versions of Node.js. As of TypeScript 5.8, `nodenext` supports `require` of ECMAScript modules. `--module nodenext` implies the floating `--target esnext`.

#### `preserve`

Expand Down
7 changes: 6 additions & 1 deletion packages/tsconfig-reference/scripts/tsconfigRules.ts
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,7 @@ export const defaultsForOptions = {
moduleResolution: [
"`Node10` if [`module`](#module) is `CommonJS`;",
"`Node16` if [`module`](#module) is `Node16` or `Node18`;",
"`Node20` if [`module`](#module) is `Node20`;",
"`NodeNext` if [`module`](#module) is `NodeNext`;",
"`Bundler` if [`module`](#module) is `Preserve`;",
"`Classic` otherwise.",
Expand All @@ -265,7 +266,11 @@ export const defaultsForOptions = {
useUnknownInCatchVariables: trueIf("strict"),
strictPropertyInitialization: trueIf("strict"),
strictNullChecks: trueIf("strict"),
target: "ES5",
target: [
"`es2023` if [`module`](#module) is `node20`;",
"`esnext` if [`module`](#module) is `nodenext`;",
"`ES5` otherwise.",
],
useDefineForClassFields: [
"`true` if [`target`](#target) is `ES2022` or higher, including `ESNext`;",
"`false` otherwise.",
Expand Down