Node.js Now Supports TypeScript Natively: Everything You Need to Know
With the release of Node.js v23.6.0, developers can now use TypeScript natively without additional transpilation tools like ts-node or manual compilation steps. This milestone significantly streamlines development workflows, simplifying build processes and improving the overall developer experience by reducing complexity.
Why This Matters
This change goes beyond reducing friction—it minimizes build complexity, eliminates an extra dependency in development environments, and allows for a more seamless experience when working with TypeScript in Node.js. Developers no longer need to set up additional compilation steps, making it easier to focus on writing code rather than configuring build pipelines.
Who Should Read This?
This guide is aimed at developers who are already familiar with Node.js and TypeScript basics. If you’re new to either, consider reviewing the Node.js documentation and TypeScript Handbook before proceeding.
A First Look at the New Feature
Here's a simple TypeScript example (demo.mts) demonstrating native support:
// demo.mts
function main(message: string): void {
console.log('Message: ' + message);
}
main('Hello!');
Previously, running TypeScript files in Node.js required a transpilation step using the TypeScript compiler (tsc
) or a tool like ts-node
. Now, we can run the file directly:
node demo.mts # Requires Node.js v23.6.0 or later
For now, running this command will produce the following warning:
ExperimentalWarning: Type Stripping is an experimental feature and might change at any time
Experimental Status and Caution
Because type stripping is still experimental, it is not recommended for production environments yet. Future changes could introduce breaking modifications. To suppress the warning in a development setup, use:
node --disable-warning=ExperimentalWarning demo.mts
For persistent suppression, add it to NODE_OPTIONS
:
export NODE_OPTIONS="--disable-warning=ExperimentalWarning"
For long-term configuration, store it in .bashrc
, .zshrc
, or .env
files, or configure it within IDE settings.
Practical Usage: Importing from Popular Libraries
A common real-world scenario is importing a popular Node.js library in TypeScript. For example:
import { writeFileSync } from 'fs';
function saveMessage(message: string): void {
writeFileSync('message.txt', message);
}
saveMessage('Hello, Node.js!');
This demonstrates how native TypeScript works seamlessly with standard Node.js modules.
Filename Extensions in Node.js TypeScript
Node.js differentiates file types by extensions:
.ts
: ESM or CommonJS, based onpackage.json
's"type"
field..mts
: Always treated as ESM..cts
: Always treated as CommonJS..tsx
: Not currently supported.
Developers must choose filenames carefully to maintain compatibility with Node.js modules. For more details on ESM vs. CommonJS, refer to Node.js documentation.
How Is Node.js TypeScript Different from Traditional TypeScript?
Node.js achieves native TypeScript support through type stripping—removing type annotations without transpilation. Key limitations and workarounds include:
Unsupported TypeScript-Specific Features and Alternatives
Feature | Supported? | Workaround | |
Enums | ❌ No | Use const enum or union types (`type Status = 'success'
| 'error'`) |
Parameter properties | ❌ No | Declare class properties explicitly in the constructor | |
Namespaces | ❌ No | Use ES modules (export {} ) instead
| |
JSX (.tsx) | ❌ No | Use Babel or tsc
| |
Experimental JS Features (decorators, pipeline operators, etc.) | ❌ No | Wait for native V8 support |
Local Imports Require .ts
Extensions
// Traditional TypeScript
import { myFunction } from './my-module.js';
// Node.js Native TypeScript
import { myFunction } from './my-module.ts';
Explicit Type Imports Required
import type { Cat, Dog } from './animal.ts';
Recommended tsconfig.json
While Node.js does not read tsconfig.json
for execution, it remains crucial for type checking and IDE support. The following minimal setup ensures smooth development:
{
"compilerOptions": {
"target": "esnext",
"module": "nodenext",
"allowImportingTsExtensions": true,
"rewriteRelativeImportExtensions": true,
"verbatimModuleSyntax": true,
"erasableSyntaxOnly": true
}
}
Why these settings matter:
allowImportingTsExtensions
: Allows importing.ts
files.rewriteRelativeImportExtensions
: Ensures correct TypeScript-to-JavaScript import conversion.verbatimModuleSyntax
: Enforces explicit type imports.erasableSyntaxOnly
: Prevents using unsupported TypeScript features.
For larger projects, running tsc --noEmit
ensures type safety without generating JavaScript files.
The --input-type
CLI Option
When running TypeScript code from stdin
or using --eval
, specify interpretation explicitly with --input-type
:
echo 'console.log("Hello" as const)' | node --input-type module-typescript
Type Stripping and Source Maps
Type stripping preserves whitespace for accurate debugging and eliminates source map dependency:
function describeColor(color: Color): string {
return `Color named "${color.colorName}"`;
}
type Color = { colorName: string };
describeColor({ colorName: 'green' });
Post-type-stripping JavaScript:
function describeColor(color ) {
return `Color named "${color.colorName}"`;
}
describeColor({ colorName: 'green' });
What's Next for Node.js TypeScript Support?
A future enhancement, --experimental-transform-types
, will introduce full TypeScript transpilation with source map support. This will allow for greater compatibility but remains an opt-in feature.
Type Stripping in Browsers: A Future Possibility?
Could type stripping enable native TypeScript execution in browsers? While theoretically feasible, obstacles such as inconsistent JavaScript engines and performance concerns remain. A timeline for browser adoption is unclear.
Quick Summary Table
Feature | Supported Natively | Notes |
Basic TypeScript Syntax | ✅ Yes | Type annotations are stripped, preserving JavaScript code |
Enums, Namespaces, Parameter Props | ❌ No | Use workarounds like union types or explicit declarations |
JSX (.tsx) | ❌ No | Requires Babel or tsc
|
Experimental JS Features (e.g., decorators) | ❌ No | Supported only when natively available in JavaScript |
Conclusion
The addition of native TypeScript support in Node.js v23.6.0 is a significant step forward, simplifying TypeScript workflows and reducing the need for additional tooling. While there are still limitations, future enhancements like --experimental-transform-types
may further expand Node.js’s TypeScript capabilities.
Looking to optimize your Node.js applications? NodeSource provides enterprise-grade insights, monitoring, and security solutions tailored for production environments. Explore how N|Solid can help you enhance performance, troubleshoot issues faster, and scale with confidence.