Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 22 additions & 20 deletions doc/api/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -977,7 +977,7 @@
and `"` are usable.

It is possible to run code containing inline types unless the
[`--no-experimental-strip-types`][] flag is provided.
[`--no-strip-types`][] flag is provided.

### `--experimental-addon-modules`

Expand Down Expand Up @@ -1586,7 +1586,7 @@

This configures Node.js to interpret `--eval` or `STDIN` input as CommonJS or
as an ES module. Valid values are `"commonjs"`, `"module"`, `"module-typescript"` and `"commonjs-typescript"`.
The `"-typescript"` values are not available with the flag `--no-experimental-strip-types`.
The `"-typescript"` values are not available with the flag `--no-strip-types`.
The default is no value, or `"commonjs"` if `--no-experimental-detect-module` is passed.

If `--input-type` is not provided,
Expand Down Expand Up @@ -1902,23 +1902,6 @@

Disable the experimental [`node:sqlite`][] module.

### `--no-experimental-strip-types`

<!-- YAML
added: v22.6.0
changes:
- version:
- v23.6.0
- v22.18.0
pr-url: https://github.com/nodejs/node/pull/56350
description: Type stripping is enabled by default.
-->

> Stability: 1.2 - Release candidate
Disable experimental type-stripping for TypeScript files.
For more information, see the [TypeScript type-stripping][] documentation.

### `--no-experimental-websocket`

<!-- YAML
Expand Down Expand Up @@ -1968,6 +1951,24 @@
Disables the family autoselection algorithm unless connection options explicitly
enables it.

### `--no-strip-types`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So the goal is to keep a stable, long-term flag to disable type stripping? Is this something that users want?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not a long term goal in the sense I wish there was no need to disable it, but given the ecosystem monkeypatches internal etc and some packages break... it's necessary

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we keep the disabling flag as experimental? I don't think we gain anything from migrating that to stable, even though we don't forsee getting rid of it just yet.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you mean rename it --no-strip-types but keep it experimental?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's the thing, I wouldn't rename it

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we want type stripping to be stable, it should feel weird to disable it. Keeping the experimental in the flag does a good job at that – albeit the word order is a bit off, but IMO that's acceptable. I'm not against adding the alias without experimental in the name, I don't think it sends the right signal is all.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I kinda agree with your point of view, the fact that can be disabled it's not something we want to drag for too long and the flag is there only for people who probably are using some library that does some monkeypatching or wrong assumption and it breaks. We have to temporarly provide users a way to disabled, we will eventually get rid of it. So --no-experimental-strip-types stays but at the same time it feels weird to call it experimental, since we mark it as stable. Whats unstable is the way to disable it.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My suggested approach is to remove experimental from the name, and in a future semver major, make it a no-op

Copy link
Member

@joyeecheung joyeecheung Nov 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 to drop the experimental prefix but I am -1 to make it a no-op in the future. That would leave no room for people getting broken to run their code on newer versions of Node.js (I don't think it's just ts-node, the other day I was running the tests of tsx and on 22 there was a regression from 20 that would go away if I disable type stripping).

I don't think having disabling option is weird for a stable feature, we have many disabling flags in Node.js for stable features. Bugs and gotchas happen and people need them to work around whatever issues their setup has with the default behavior. That's fine, the default may work for 99% of the people but there can always be 1% that really have to disable it to be able to run their code at all. For example some time ago I added --disable-wasm-trap-handler because in some environments, the WASM trap handler would make it impossible to run WASM at all. But WASM trap-based bound checks should still be considered stable and perfectly fine to use to provide significant speed up for WASM code. Its design just unfortunately doesn't work in certain niche environments and people have to accept the slowdown for keeping their app functional at all.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in a future semver major, make it a no-op

If you meant "make --strip-types a no-op, then sure that can be discussed; if you mean "make --no-strip-types a no-op, that would be quite weird, it's not how we usually handles such flags (e.g. --experimental-top-level-await is still accepted, --no-experimental-top-level-await throws).

+1 to drop the experimental prefix

But we're not dropping the experimental one, we're adding a new flag that has the same effect, so now we have two.
Anyway, either way is fine, it's not like the additional flag would be a maintenance burden, and I don't feel strongly about the name.


<!-- YAML
added: v22.6.0
changes:
- version: REPLACEME
pr-url: https://github.com/nodejs/node/pull/60600
description: Type stripping is now stable.
- version:
- v23.6.0
- v22.18.0
pr-url: https://github.com/nodejs/node/pull/56350

Check warning on line 1965 in doc/api/cli.md

View workflow job for this annotation

GitHub Actions / lint-pr-url

pr-url doesn't match the URL of the current PR.
description: Type stripping is enabled by default.
-->

Disable type-stripping for TypeScript files.
For more information, see the [TypeScript type-stripping][] documentation.

### `--no-warnings`

<!-- YAML
Expand Down Expand Up @@ -3548,6 +3549,7 @@
* `--no-force-async-hooks-checks`
* `--no-global-search-paths`
* `--no-network-family-autoselection`
* `--no-strip-types`
* `--no-warnings`
* `--no-webstorage`
* `--node-memory-debug`
Expand Down Expand Up @@ -4111,7 +4113,7 @@
[`--experimental-sea-config`]: single-executable-applications.md#generating-single-executable-preparation-blobs
[`--heap-prof-dir`]: #--heap-prof-dir
[`--import`]: #--importmodule
[`--no-experimental-strip-types`]: #--no-experimental-strip-types
[`--no-strip-types`]: #--no-strip-types
[`--openssl-config`]: #--openssl-configfile
[`--preserve-symlinks`]: #--preserve-symlinks
[`--print`]: #-p---print-script
Expand Down
6 changes: 5 additions & 1 deletion doc/api/process.md
Original file line number Diff line number Diff line change
Expand Up @@ -2001,6 +2001,10 @@ This value is therefore identical to that of `process.features.tls`.
added:
- v23.0.0
- v22.10.0
changes:
- version: REPLACEME
pr-url: https://github.com/nodejs/node/pull/60600
description: Type stripping is now stable.
-->

> Stability: 1.2 - Release candidate
Expand All @@ -2009,7 +2013,7 @@ added:

A value that is `"strip"` by default,
`"transform"` if Node.js is run with `--experimental-transform-types`, and `false` if
Node.js is run with `--no-experimental-strip-types`.
Node.js is run with `--no-strip-types`.

## `process.features.uv`

Expand Down
4 changes: 2 additions & 2 deletions doc/api/test.md
Original file line number Diff line number Diff line change
Expand Up @@ -514,7 +514,7 @@ By default, Node.js will run all files matching these patterns:
* `**/test.{cjs,mjs,js}`
* `**/test/**/*.{cjs,mjs,js}`

Unless [`--no-experimental-strip-types`][] is supplied, the following
Unless [`--no-strip-types`][] is supplied, the following
additional patterns are also matched:

* `**/*.test.{cts,mts,ts}`
Expand Down Expand Up @@ -3996,7 +3996,7 @@ Can be used to abort test subtasks when the test has been aborted.
[`--experimental-test-coverage`]: cli.md#--experimental-test-coverage
[`--experimental-test-module-mocks`]: cli.md#--experimental-test-module-mocks
[`--import`]: cli.md#--importmodule
[`--no-experimental-strip-types`]: cli.md#--no-experimental-strip-types
[`--no-strip-types`]: cli.md#--no-strip-types
[`--test-concurrency`]: cli.md#--test-concurrency
[`--test-coverage-exclude`]: cli.md#--test-coverage-exclude
[`--test-coverage-include`]: cli.md#--test-coverage-include
Expand Down
13 changes: 10 additions & 3 deletions doc/api/typescript.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

<!-- YAML
changes:
- version: REPLACEME
pr-url: https://github.com/nodejs/node/pull/60600
description: Type stripping is now stable.
- version:
- v24.3.0
- v22.18.0
Expand All @@ -19,7 +22,7 @@ changes:

<!--introduced_in=v22.6.0-->

> Stability: 1.2 - Release candidate
> Stability: 2 - Stable
## Enabling

Expand Down Expand Up @@ -60,6 +63,10 @@ To use TypeScript with full support for all TypeScript features, including

<!-- YAML
added: v22.6.0
changes:
- version: REPLACEME
pr-url: https://github.com/nodejs/node/pull/60600
description: Type stripping is now stable.
-->

By default Node.js will execute TypeScript files that contains only
Expand All @@ -68,7 +75,7 @@ Node.js will replace TypeScript syntax with whitespace,
and no type checking is performed.
To enable the transformation of non erasable TypeScript syntax, which requires JavaScript code generation,
such as `enum` declarations, parameter properties use the flag [`--experimental-transform-types`][].
To disable this feature, use the flag [`--no-experimental-strip-types`][].
To disable this feature, use the flag [`--no-strip-types`][].

Node.js ignores `tsconfig.json` files and therefore
features that depend on settings within `tsconfig.json`,
Expand Down Expand Up @@ -219,7 +226,7 @@ with `#`.
[ES Modules]: esm.md
[Full TypeScript support]: #full-typescript-support
[`--experimental-transform-types`]: cli.md#--experimental-transform-types
[`--no-experimental-strip-types`]: cli.md#--no-experimental-strip-types
[`--no-strip-types`]: cli.md#--no-strip-types
[`ERR_UNSUPPORTED_TYPESCRIPT_SYNTAX`]: errors.md#err_unsupported_typescript_syntax
[`tsconfig` "paths"]: https://www.typescriptlang.org/tsconfig/#paths
[`tsx`]: https://tsx.is/
Expand Down
6 changes: 3 additions & 3 deletions doc/contributing/advocacy-ambassador-program.md
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ You can find their contact email in the [`README.md`](../../README.md#tsc-techni

##### Goal

The goal is to raise awareness of the Node.js TypeScript Type Stripping in the JavaScript ecosystem.
The goal is to raise awareness of the Node.js TypeScript Type stripping in the JavaScript ecosystem.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Why capitalise "Type" but not "stripping"?

Copy link
Member Author

@marco-ippolito marco-ippolito Nov 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Idk 😆 I've read "Type Stripping", "Type stripping", "type-stripping" not sure which one is correct

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it should be "type stripping", personally

/ducks

Some of the things to highlight include:

* The benefits and limitations of the current implementation.
Expand Down Expand Up @@ -271,7 +271,7 @@ with projects learning from one another and their users.
| [reading environment](https://nodejs.org/api/cli.html#--env-filefile) | [20.6.0](https://nodejs.org/en/blog/release/v20.6.0) | Active Development |
| [styling output](https://nodejs.org/docs/latest-v22.x/api/util.html#utilstyletextformat-text-options) | [20.12.0](https://nodejs.org/en/blog/release/v20.12.0) | Stable, as of [22.13.0](https://github.com/nodejs/node/pull/56329) |
| [run scripts](https://nodejs.org/docs/latest/api/cli.html#--run) | [22.0.0](https://nodejs.org/en/blog/release/v22.0.0) | Stable, as of 22.0.0 |
| [run TypeScript](https://nodejs.org/api/cli.html#--experimental-strip-types) | [22.6.0](https://nodejs.org/en/blog/release/v22.6.0) | Active Development |
| [run TypeScript](https://nodejs.org/api/cli.html#--strip-types) | [22.6.0](https://nodejs.org/en/blog/release/v22.6.0) | Stable, as of REPLACEME |

##### Related Links

Expand All @@ -284,7 +284,7 @@ with projects learning from one another and their users.
* <https://nodejs.org/api/cli.html#--env-filefile>
* <https://nodejs.org/docs/latest-v22.x/api/util.html#utilstyletextformat-text-options>
* <https://nodejs.org/api/cli.html#--run>
* <https://nodejs.org/api/cli.html#--experimental-strip-types>
* <https://nodejs.org/api/cli.html#--strip-types>

<!-- lint enable prohibited-strings remark-lint-->

Expand Down
6 changes: 3 additions & 3 deletions doc/node-config-schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -177,9 +177,6 @@
"experimental-sqlite": {
"type": "boolean"
},
"experimental-strip-types": {
"type": "boolean"
},
"experimental-transform-types": {
"type": "boolean"
},
Expand Down Expand Up @@ -361,6 +358,9 @@
"stack-trace-limit": {
"type": "number"
},
"strip-types": {
"type": "boolean"
},
"test-coverage-branches": {
"type": "number"
},
Expand Down
4 changes: 2 additions & 2 deletions doc/node.1
Original file line number Diff line number Diff line change
Expand Up @@ -216,8 +216,8 @@ Disable top-level await keyword support in REPL.
.It Fl -no-experimental-sqlite
Disable the experimental node:sqlite module.
.
.It Fl -no-experimental-strip-types
Disable experimental type-stripping for TypeScript files.
.It Fl -no-strip-types
Disable type-stripping for TypeScript files.
.
.It Fl -experimental-vm-modules
Enable experimental ES module support in VM module.
Expand Down
2 changes: 1 addition & 1 deletion lib/internal/bootstrap/node.js
Original file line number Diff line number Diff line change
Expand Up @@ -334,7 +334,7 @@ ObjectDefineProperty(process.features, 'typescript', {
if (kTypeStrippingMode === null) {
if (getOptionValue('--experimental-transform-types')) {
kTypeStrippingMode = 'transform';
} else if (getOptionValue('--experimental-strip-types')) {
} else if (getOptionValue('--strip-types')) {
kTypeStrippingMode = 'strip';
} else {
kTypeStrippingMode = false;
Expand Down
2 changes: 1 addition & 1 deletion lib/internal/main/eval_stdin.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ readStdin((code) => {
const print = getOptionValue('--print');
const shouldLoadESM = getOptionValue('--import').length > 0;
const inputType = getOptionValue('--input-type');
const tsEnabled = getOptionValue('--experimental-strip-types');
const tsEnabled = getOptionValue('--strip-types');
if (inputType === 'module') {
evalModuleEntryPoint(code, print);
} else if (inputType === 'module-typescript' && tsEnabled) {
Expand Down
2 changes: 1 addition & 1 deletion lib/internal/main/eval_string.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ const code = getOptionValue('--eval');
const print = getOptionValue('--print');
const shouldLoadESM = getOptionValue('--import').length > 0 || getOptionValue('--experimental-loader').length > 0;
const inputType = getOptionValue('--input-type');
const tsEnabled = getOptionValue('--experimental-strip-types');
const tsEnabled = getOptionValue('--strip-types');
if (inputType === 'module') {
evalModuleEntryPoint(code, print);
} else if (inputType === 'module-typescript' && tsEnabled) {
Expand Down
2 changes: 1 addition & 1 deletion lib/internal/main/worker_thread.js
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ port.on('message', (message) => {
value: filename,
});
ArrayPrototypeSplice(process.argv, 1, 0, name);
const tsEnabled = getOptionValue('--experimental-strip-types');
const tsEnabled = getOptionValue('--strip-types');
const inputType = getOptionValue('--input-type');

if (inputType === 'module-typescript' && tsEnabled) {
Expand Down
2 changes: 1 addition & 1 deletion lib/internal/modules/cjs/loader.js
Original file line number Diff line number Diff line change
Expand Up @@ -1856,7 +1856,7 @@ function getRequireESMError(mod, pkg, content, filename) {
*/
Module._extensions['.js'] = function(module, filename) {
let format, pkg;
const tsEnabled = getOptionValue('--experimental-strip-types');
const tsEnabled = getOptionValue('--strip-types');
if (StringPrototypeEndsWith(filename, '.cjs')) {
format = 'commonjs';
} else if (StringPrototypeEndsWith(filename, '.mjs')) {
Expand Down
2 changes: 1 addition & 1 deletion lib/internal/modules/esm/formats.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ if (experimentalAddonModules) {
extensionFormatMap['.node'] = 'addon';
}

if (getOptionValue('--experimental-strip-types')) {
if (getOptionValue('--strip-types')) {
extensionFormatMap['.ts'] = 'module-typescript';
extensionFormatMap['.mts'] = 'module-typescript';
extensionFormatMap['.cts'] = 'commonjs-typescript';
Expand Down
4 changes: 2 additions & 2 deletions lib/internal/modules/esm/get_format.js
Original file line number Diff line number Diff line change
Expand Up @@ -132,15 +132,15 @@ function getFileProtocolModuleFormat(url, context = { __proto__: null }, ignoreE
}
return format;
}
if (ext === '.ts' && getOptionValue('--experimental-strip-types')) {
if (ext === '.ts' && getOptionValue('--strip-types')) {
const { type: packageType, pjsonPath, exists: foundPackageJson } = getPackageScopeConfig(url);
if (packageType !== 'none') {
return `${packageType}-typescript`;
}
// The controlling `package.json` file has no `type` field.
// `source` is undefined when this is called from `defaultResolve`;
// but this gets called again from `defaultLoad`/`defaultLoadSync`.
// Since experimental-strip-types depends on detect-module, we always return null if source is undefined.
// Since strip-types depends on detect-module, we always return null if source is undefined.
if (!source) { return null; }
const { stringify } = require('internal/modules/helpers');
const { stripTypeScriptModuleTypes } = require('internal/modules/typescript');
Expand Down
2 changes: 1 addition & 1 deletion lib/internal/modules/run_main.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ function shouldUseESMLoader(mainPath) {
if (mainPath && StringPrototypeEndsWith(mainPath, '.wasm')) { return true; }
if (!mainPath || StringPrototypeEndsWith(mainPath, '.cjs')) { return false; }

if (getOptionValue('--experimental-strip-types')) {
if (getOptionValue('--strip-types')) {
if (!mainPath || StringPrototypeEndsWith(mainPath, '.cts')) { return false; }
// This will likely change in the future to start with commonjs loader by default
if (mainPath && StringPrototypeEndsWith(mainPath, '.mts')) { return true; }
Expand Down
2 changes: 1 addition & 1 deletion lib/internal/process/execution.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ function evalScript(name, body, breakFirstLine, print, shouldLoadESM = false) {
const baseUrl = pathToFileURL(module.filename).href;

if (shouldUseModuleEntryPoint(name, body)) {
return getOptionValue('--experimental-strip-types') ?
return getOptionValue('--strip-types') ?
evalTypeScriptModuleEntryPoint(body, print) :
evalModuleEntryPoint(body, print);
}
Expand Down
2 changes: 1 addition & 1 deletion lib/internal/test_runner/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ const kRegExpPattern = /^\/(.*)\/([a-z]*)$/;

const kPatterns = ['test', 'test/**/*', 'test-*', '*[._-]test'];
const kFileExtensions = ['js', 'mjs', 'cjs'];
if (getOptionValue('--experimental-strip-types')) {
if (getOptionValue('--strip-types')) {
ArrayPrototypePush(kFileExtensions, 'ts', 'mts', 'cts');
}
const kDefaultPattern = `**/{${ArrayPrototypeJoin(kPatterns, ',')}}.{${ArrayPrototypeJoin(kFileExtensions, ',')}}`;
Expand Down
9 changes: 5 additions & 4 deletions src/node_options.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1071,17 +1071,18 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() {
"ES module to preload (option can be repeated)",
&EnvironmentOptions::preload_esm_modules,
kAllowedInEnvvar);
AddOption("--experimental-strip-types",
"Experimental type-stripping for TypeScript files.",
&EnvironmentOptions::experimental_strip_types,
AddOption("--strip-types",
"Type-stripping for TypeScript files.",
&EnvironmentOptions::strip_types,
kAllowedInEnvvar,
true);
AddAlias("--experimental-strip-types", "--strip-types");
AddOption("--experimental-transform-types",
"enable transformation of TypeScript-only"
"syntax into JavaScript code",
&EnvironmentOptions::experimental_transform_types,
kAllowedInEnvvar);
Implies("--experimental-transform-types", "--experimental-strip-types");
Implies("--experimental-transform-types", "--strip-types");
Implies("--experimental-transform-types", "--enable-source-maps");
AddOption("--interactive",
"always enter the REPL even if stdin does not appear "
Expand Down
2 changes: 1 addition & 1 deletion src/node_options.h
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,7 @@ class EnvironmentOptions : public Options {

std::vector<std::string> preload_esm_modules;

bool experimental_strip_types = true;
bool strip_types = true;
bool experimental_transform_types = false;

std::vector<std::string> user_argv;
Expand Down
Loading