Skip to content
Closed
Prev Previous commit
Next Next commit
module: remove experimental warning from type stripping
PR-URL: #58643
Refs: nodejs/typescript#24
Reviewed-By: Jacob Smith <jacob@frende.me>
Reviewed-By: Michaël Zasso <targos@protonmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Jordan Harband <ljharb@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Filip Skokan <panva.ip@gmail.com>
Reviewed-By: Ethan Arrowood <ethan@arrowood.dev>
Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com>
Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
Reviewed-By: Chemi Atlow <chemi@atlow.co.il>
  • Loading branch information
marco-ippolito committed Jul 3, 2025
commit 59c3c01bc88b007349ee2cada5a7f9e864878b5b
3 changes: 3 additions & 0 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/58643
description: Type stripping no longer emits an experimental warning.
- version: REPLACEME
pr-url: https://github.com/nodejs/node/pull/56350
description: Type stripping is enabled by default.
Expand Down
9 changes: 3 additions & 6 deletions lib/internal/modules/typescript.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ const { Buffer } = require('buffer');
* @type {string}
*/
const getTypeScriptParsingMode = getLazy(() =>
(getOptionValue('--experimental-transform-types') ? 'transform' : 'strip-only'),
(getOptionValue('--experimental-transform-types') ?
(emitExperimentalWarning('Transform Types'), 'transform') : 'strip-only'),
);

/**
Expand Down Expand Up @@ -131,13 +132,9 @@ function processTypeScriptCode(code, options) {
* It is used by internal loaders.
* @param {string} source TypeScript code to parse.
* @param {string} filename The filename of the source code.
* @param {boolean} emitWarning Whether to emit a warning.
* @returns {TransformOutput} The stripped TypeScript code.
*/
function stripTypeScriptModuleTypes(source, filename, emitWarning = true) {
if (emitWarning) {
emitExperimentalWarning('Type Stripping');
}
function stripTypeScriptModuleTypes(source, filename) {
assert(typeof source === 'string');
if (isUnderNodeModules(filename)) {
throw new ERR_UNSUPPORTED_NODE_MODULES_TYPE_STRIPPING(filename);
Expand Down
9 changes: 2 additions & 7 deletions lib/internal/process/execution.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ const { getOptionValue } = require('internal/options');
const {
makeContextifyScript, runScriptInThisContext,
} = require('internal/vm');
const { emitExperimentalWarning } = require('internal/util');
// shouldAbortOnUncaughtToggle is a typed array for faster
// communication with JS.
const { shouldAbortOnUncaughtToggle } = internalBinding('util');
Expand Down Expand Up @@ -255,16 +254,14 @@ function evalTypeScript(name, source, breakFirstLine, print, shouldLoadESM = fal
compiledScript = compileScript(name, source, baseUrl);
} catch (originalError) {
try {
sourceToRun = stripTypeScriptModuleTypes(source, name, false);
sourceToRun = stripTypeScriptModuleTypes(source, kEvalTag);
// Retry the CJS/ESM syntax detection after stripping the types.
if (shouldUseModuleEntryPoint(name, sourceToRun)) {
return evalTypeScriptModuleEntryPoint(source, print);
}
// If the ContextifiedScript was successfully created, execute it.
// outside the try-catch block to avoid catching runtime errors.
compiledScript = compileScript(name, sourceToRun, baseUrl);
// Emit the experimental warning after the code was successfully evaluated.
emitExperimentalWarning('Type Stripping');
} catch (tsError) {
// If it's invalid or unsupported TypeScript syntax, rethrow the original error
// with the TypeScript error message added to the stack.
Expand Down Expand Up @@ -318,12 +315,10 @@ function evalTypeScriptModuleEntryPoint(source, print) {
moduleWrap = loader.createModuleWrap(source, url);
} catch (originalError) {
try {
const strippedSource = stripTypeScriptModuleTypes(source, url, false);
const strippedSource = stripTypeScriptModuleTypes(source, kEvalTag);
// If the moduleWrap was successfully created, execute the module job.
// outside the try-catch block to avoid catching runtime errors.
moduleWrap = loader.createModuleWrap(strippedSource, url);
// Emit the experimental warning after the code was successfully compiled.
emitExperimentalWarning('Type Stripping');
} catch (tsError) {
// If it's invalid or unsupported TypeScript syntax, rethrow the original error
// with the TypeScript error message added to the stack.
Expand Down
10 changes: 5 additions & 5 deletions test/es-module/test-typescript-eval.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ test('eval TypeScript ESM syntax', async () => {
const text: string = 'Hello, TypeScript!'
console.log(util.styleText('red', text));`]);

match(result.stderr, /Type Stripping is an experimental feature and might change at any time/);
strictEqual(result.stderr, '');
match(result.stdout, /Hello, TypeScript!/);
strictEqual(result.code, 0);
});
Expand All @@ -24,7 +24,7 @@ test('eval TypeScript ESM syntax with input-type module', async () => {
const text: string = 'Hello, TypeScript!'
console.log(util.styleText('red', text));`]);

match(result.stderr, /Type Stripping is an experimental feature and might change at any time/);
strictEqual(result.stderr, '');
match(result.stdout, /Hello, TypeScript!/);
strictEqual(result.code, 0);
});
Expand All @@ -36,7 +36,7 @@ test('eval TypeScript CommonJS syntax', async () => {
const text: string = 'Hello, TypeScript!'
console.log(util.styleText('red', text));`]);
match(result.stdout, /Hello, TypeScript!/);
match(result.stderr, /ExperimentalWarning: Type Stripping is an experimental/);
strictEqual(result.stderr, '');
strictEqual(result.code, 0);
});

Expand Down Expand Up @@ -72,7 +72,7 @@ test('TypeScript ESM syntax not specified', async () => {
`import util from 'node:util'
const text: string = 'Hello, TypeScript!'
console.log(text);`]);
match(result.stderr, /ExperimentalWarning: Type Stripping is an experimental/);
strictEqual(result.stderr, '');
match(result.stdout, /Hello, TypeScript!/);
strictEqual(result.code, 0);
});
Expand Down Expand Up @@ -162,7 +162,7 @@ test('check warning is emitted when eval TypeScript CommonJS syntax', async () =
`const util = require('node:util');
const text: string = 'Hello, TypeScript!'
console.log(util.styleText('red', text));`]);
match(result.stderr, /ExperimentalWarning: Type Stripping is an experimental/);
strictEqual(result.stderr, '');
match(result.stdout, /Hello, TypeScript!/);
strictEqual(result.code, 0);
});
Expand Down
2 changes: 1 addition & 1 deletion test/es-module/test-typescript-module.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ test('execute an .mts file importing an .mts file', async () => {
fixtures.path('typescript/mts/test-import-module.mts'),
]);

match(result.stderr, /Type Stripping is an experimental feature and might change at any time/);
strictEqual(result.stderr, '');
match(result.stdout, /Hello, TypeScript!/);
strictEqual(result.code, 0);
});
Expand Down
13 changes: 12 additions & 1 deletion test/es-module/test-typescript.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ test('execute a TypeScript file', async () => {
fixtures.path('typescript/ts/test-typescript.ts'),
]);

match(result.stderr, /Type Stripping is an experimental feature and might change at any time/);
strictEqual(result.stderr, '');
match(result.stdout, /Hello, TypeScript!/);
strictEqual(result.code, 0);
});
Expand Down Expand Up @@ -412,3 +412,14 @@ test('execute invalid TypeScript syntax', async () => {
strictEqual(result.stdout, '');
strictEqual(result.code, 1);
});

test('check transform types warning', async () => {
const result = await spawnPromisified(process.execPath, [
'--experimental-transform-types',
fixtures.path('typescript/ts/test-typescript.ts'),
]);

match(result.stderr, /Transform Types is an experimental feature and might change at any time/);
match(result.stdout, /Hello, TypeScript!/);
strictEqual(result.code, 0);
});