How do you usually use Node.js? Node.js is a JavaScript runtime that runs on the server side. It is used in many situations. For example, it can build real-time web content together with Socket.IO. It also powers tools for front-end engineers, including Vite and webpack.
For large-scale development with Node.js, TypeScript is a recommended choice. Introducing TypeScript can improve development productivity and maintainability. When used with WebStorm or Visual Studio Code, TypeScript offers the following benefits.
- Code completion dramatically improves programming efficiency
- Static typing improves safety by running type checks at compile time
There are several ways to use TypeScript with Node.js. This article explains the basic setup for writing Node.js code in TypeScript using the following three configurations.
- Native Node.js (v23.6.0 and later)
- ts-node (TypeScript runner)
- tsx (fast esbuild-based runner)
Why are there multiple approaches?
Originally, Node.js could only run JavaScript.
TypeScript is a superset of JavaScript, so to run TypeScript in Node.js, TypeScript needs to be converted to JavaScript. Starting with Node.js v23.6.0, Node.js can ignore information such as TypeScript type annotations and run the file as JavaScript. Because this requires almost no setup, it is the easiest way to run TypeScript with Node.js.
On the other hand, environments earlier than Node.js v23.6.0 need a different approach, such as ts-node or tsx.
Each approach has its own advantages, which this article explains.
The sample code for this article is available on GitHub, so download it and follow along.
The sample code supports TypeScript 7.
Setting up a TypeScript environment
First, prepare the environment. Install Node.js. Use the installer on the official website and follow the instructions. Be sure to install Node.js version 23.6.0 or later. Node.js v23.6.0 and later can run TypeScript.
After installation, run node -v from the command line (Terminal.app on macOS, or Command Prompt on Windows). If the Node.js version appears, the installation was successful.
node -v
If a version such as v23.6.0 appears in the command line, the installation was successful.
Next, run the following command in your working folder. This creates a package.json file.
npm init -y
Then install TypeScript. Run the following command from the command line. Node.js can run the file even without installing TypeScript, but TypeScript must be installed to use features such as type checking.
npm install typescript @types/node -D
This also prepares the type declaration files for Node.js. TypeScript alone does not know which methods and variables exist in Node.js modules, so compilation may fail. Loading type declaration files also enables code completion in editors that support TypeScript.
Next, configure TypeScript compilation. Node.js does not refer to tsconfig.json when directly executing .ts files, but it is still useful for type checking with tsc and editor completion. Create a tsconfig.json file at the same level as package.json with the following content.
tsconfig.json
{
"compilerOptions": {
// Match Node.js ESM/CJS resolution
"module": "NodeNext",
// Allow imports of files with the .ts extension
"allowImportingTsExtensions": true,
// TypeScript 6 and later use [] as the default for types, so specify Node.js types explicitly
"types": ["node"]
}
}
Modify package.json slightly so that it looks like the following. Execution commands for each sample and a typecheck command have been added to the scripts field. This enables TypeScript type checking.
package.json
{
"scripts": {
"example1": "node example1/index.ts",
"example2": "node example2/index.ts",
"example3": "node example3/index.ts",
"typecheck": "tsc --noEmit"
},
"private": true,
"type": "module",
"devDependencies": {
"@types/node": "^26.1.1",
"typescript": "^7.0.2"
}
}
Creating a TypeScript file
Now write Node.js code in TypeScript. Create a new text file named index.ts inside the example1 folder. Write the following code in index.ts using a text editor.
console.log("Hello! Node.js × TypeScript");
Run the node command from the command line to execute Node.js. You should see Hello! Node.js × TypeScript printed in the command line.
node example1/index.ts
Fetching data from the network
Now try a slightly more complex process. Node.js can fetch data from the network. Create an example2 folder, then create a file named index.ts inside it. Write the following code. This sample uses the Japan Meteorological Agency Web API to fetch the weather forecast for Tokyo.
// URL for fetching the weather forecast overview for a specified Japan Meteorological Agency area
const url = "https://www.jma.go.jp/bosai/forecast/data/overview_forecast/130000.json";
/**
* Fetches weather forecast data, formats it, and outputs it to the console.
*/
async function start() {
// Fetch data from the URL asynchronously
const response = await fetch(url);
// Convert the fetched response to JSON
const data = await response.json();
// Format the fetched JSON data and output it to the console
console.log(JSON.stringify(data, null, 2));
}
start();
Run the following command from the command line.
node example2/index.ts
This fetches JSON data from the Japan Meteorological Agency and prints it in the command line.
> node example2/index.ts
{
"publishingOffice": "Japan Meteorological Agency",
"reportDatetime": "2025-05-14T16:34:00+09:00",
"targetArea": "Tokyo",
"headlineText": "",
"text": "The Kanto-Koshin region is under the influence of a high-pressure system.\n\nThe Tokyo area is sunny or cloudy.\n\nOn the 14th, the region is expected to be under the influence of a high-pressure system, but it will also be affected by a trough and moist air.\n\n[Kanto-Koshin region]\nThe Kanto-Koshin region is sunny or cloudy.\n\nOn the 14th, the region is expected to be under the influence of a high-pressure system, but it will also be affected by a trough and moist air. As a result, it will be sunny or cloudy, with rain in some areas.\n\nOver the waters around the Kanto region and the Izu Islands, waves are expected to be slightly high from the 14th to the 15th. Fog is also expected in some places. Vessels should be careful of reduced visibility."
}
Create an external module and split the code across files
As a script grows longer, splitting the processing into separate files by feature and creating external modules makes the code easier to understand. Here, move the URL constant above into an external file. Create an external file named config.ts at the same level as index.ts, then import it from index.ts. Note that variables loaded from another file must be marked with export.
config.ts
/** Target URL */
export const TARGET_URL = "https://www.jma.go.jp/bosai/forecast/data/overview_forecast/130000.json";
In index.ts, which loads this file, use an import statement just like loading a Node.js module. The .ts extension cannot be omitted.
index.ts
// Load the external file
import {TARGET_URL} from './config.ts';
/**
* Fetches weather forecast data, formats it, and outputs it to the console.
* @param url URL to fetch
*/
async function start(url:string) {
// Fetch data from the URL asynchronously
const response = await fetch(url);
// Convert the fetched response to JSON
const data = await response.json();
// Format the fetched JSON data and output it to the console
console.log(JSON.stringify(data, null, 2));
}
start(TARGET_URL);
Run this file by entering the following command.
node example3/index.ts
If the JSON data from the Japan Meteorological Agency is fetched as before, it worked. The main process was able to reference a variable defined in the external file config.ts.
Static type checking
One important point is that executing .ts files with the node command does not perform type checking. Even if the code is wrong, Node.js runs it as is. For example, even though the start() function in index.ts specifies a string parameter, passing the number 123 as a number does not produce an error. The code will fail later at runtime, but ideally this should be a compile error at the argument stage.
start(123); // Passing a number does not produce a compile error
To handle this, use the tsc command to run TypeScript type checking. tsc is the TypeScript compiler. It not only converts TypeScript to JavaScript, but also performs type checking. The typecheck command has already been added to the scripts field in package.json, so run the following command.
npm run typecheck
If TypeScript finds type errors, compile errors are displayed. Fix the code until all errors are resolved.
This completes the TypeScript execution environment for Node.js. For small-scale development, running files directly with the Node.js node command is convenient.
Setting up a TypeScript environment with ts-node
Versions earlier than Node.js v23.6.0 cannot execute TypeScript directly. In those environments, TypeScript must be compiled into JavaScript before it can be executed with Node.js.
The package that enables TypeScript to run on Node.js is ts-node. ts-node is a runner that executes .ts files using the TypeScript compiler. It can be used even in environments where Node.js cannot run TypeScript natively.
In this sample, only the ts-node setup uses TypeScript 6. Use npm run start to execute the code, and use npm run typecheck to run type checking.
Run the following commands to install the required packages.
npm install typescript@^6 ts-node
npm install @types/node -D
Then add a start command to the scripts field in package.json.
package.json
{
"scripts": {
"start": "ts-node example3/index.ts",
"typecheck": "tsc --noEmit"
},
"dependencies": {
"typescript": "^6.0.2",
"ts-node": "^10.9.2"
},
"devDependencies": {
"@types/node": "^26.1.1"
},
"private": true
}
Next, configure TypeScript compilation. Create a tsconfig.json file at the same level as package.json with the following content.
tsconfig.json
{
"compilerOptions": {
// Match Node.js ESM/CJS resolution
"module": "NodeNext",
// Allow imports of files with the .ts extension
"allowImportingTsExtensions": true,
// TypeScript 6 and later use [] as the default for types, so specify Node.js types explicitly
"types": ["node"]
}
}
This completes the environment for writing Node.js code in TypeScript. It runs with the npm run start command. Type checking can be executed with npm run typecheck.
The sample code is available below.
Setting up a TypeScript environment with tsx
Because ts-node compiles TypeScript before executing it, compilation takes time. ts-node is useful during development, but its drawback is slower execution. An alternative to ts-node is tsx. Internally, tsx uses esbuild to compile and execute TypeScript, so it can run faster than ts-node.
Install it with the following commands.
npm install tsx typescript
npm install @types/node -D
tsx does not have a type checking feature, so run the tsc command to perform type checking. Add a typecheck command to the scripts field in package.json.
{
"scripts": {
"start": "tsx example3/index.ts",
"typecheck": "tsc --noEmit"
},
"private": true,
"dependencies": {
"tsx": "^4.23.0",
"typescript": "^7.0.2"
},
"devDependencies": {
"@types/node": "^26.1.1"
}
}
Because tsx also uses imports with the .ts extension, prepare tsconfig.json with the following content.
tsconfig.json
{
"compilerOptions": {
// Match Node.js ESM/CJS resolution
"module": "NodeNext",
// Allow imports of files with the .ts extension
"allowImportingTsExtensions": true,
// TypeScript 6 and later use [] as the default for types, so specify Node.js types explicitly
"types": ["node"]
}
}
The sample code is available below.
Native Node.js, ts-node, or tsx?
Native Node.js can run .ts files as they are, but what advantages do ts-node and tsx provide? Native Node.js does not read tsconfig.json at all. IDEs and similar tools simply read tsconfig.json on their own and detect code errors in the editor. If your project uses more complex tsconfig.json settings, you need ts-node or tsx.
In particular, ts-node and tsx support “handling JSX/TSX files such as React” and “resolving paths in tsconfig.json.”
Conclusion
Writing Node.js code in TypeScript gives you the benefits of static typing and makes large-scale development and maintenance easier.
Adding startup commands and type checking commands to npm scripts also makes development easier. For more about npm scripts, see the article npm-scriptsのタスク実行方法.

