Node.js TypeScript #1. Modules, process arguments, basics of the File System

JavaScript Node.js

This entry is part 1 of 15 in the Node.js TypeScript

In this series, we go through the core concepts of Node.js. In general, in this series, we focus on the environment of Node.js and not the JavaScript itself, while having the advantages of static typing using TypeScript. It includes matters like the File System, Event Loop, and the Worker Threads. In this article, we create a script that can create and read files based on arguments passed when executing it. While we don’t create any particular web application here, we learn how Node.js handles files and server connections what might prove to be helpful in many situations. If you would like to know how to create applications with the Express framework, check out my Node.js TypeScript Express tutorial.

Node.js TypeScript: the basics of Node.js

At first, let’s elaborate on what Node.js is because it is sometimes misunderstood. In short, it is an environment that can run JavaScript outside of a browser, and that means that after installing Node.js, you can fire up your terminal and execute JavaScript code!

Node.js TypeScript terminal

If you wrote some Front-End code, chances are you already have Node.js installed since Node Package Manager comes with it. You can find out with a simple command.


Although this series aims to use TypeScript, it is essential to understand how Node.js modules work and how to use them.

Let’s start by writing a quite peculiar piece of code:

This example might seem odd because the ECMAScript specification states the following:

An ECMAScript program is considered syntactically incorrect if it contains a return statement
that is not within a FunctionBody.

When you run it, you can see that no errors were displayed and the program logged  . This due to the fact, that in Node.js, each file is treated as a separate module. Under the hood, Node.js wraps them in a function like this:

Thanks to that, the top-level variables are scoped to the module and are not global throughout the whole project. The module object can be used to export values:


To access it from another file, we use the require function.


This module system is an implementation of the CommonJS format.

Node.js invokes the function that wraps our module a way, that the “this” keyword references to the module.exports. We can easily prove that:

The above is often a cause of confusion because if you are running Node.js in a console, the “this” keyword references to the global object.

As of the time of writing this article, the ES6 modules are under active development and might at some point be stable.

Global object

Being a JavaScript developer, you encounter the window object. In Node.js, we have the “global” object. You can think of it as its counterpart.

When your run Node.js in the terminal and executing a particular file, Node.js does not wrap your code in a module. When using Node.js in the terminal, you are in the global scope, the “this” keyword references to the global object. Then, the variables declared with var are attached to the global object:

Node.js TypeScript terminal

This object is shared between all your modules. If we were to assign some property to it, it would be accessible everywhere.

Process arguments

The process object is a property of the global object, and therefore it is available throughout your application. It comes in handy when gathering information about the environment of our Node.js app, such as the currently installed version of Node.js. We dive into it more along the way in this series, and today we focus on the process.argv property. It holds an array containing the command line arguments you pass when launching the Node.js process.

The first element is the same as the process.execPath and it holds the absolute pathname of the executable that started the Node.js process.

The second element is a path to the executed JavaScript file. The rest of the process.argv elements are any additional command line arguments.


Running a  Node.js Typescript project

To run our scripts using TypeScript we need to initialize our project using npm and install TypeScript and ts-node.

To run ts-node from within our node_modules directory, we make a new script in our package.json:

For this series, I use a tsconfig file like that one:


We’re all set to start using TypeScript with Node.js!

With TypeScript Node.js we use imports and exports like in ES6 Modules, but since Node.js does not yet support them, ts-node transpiles our code to CommonJS. You can find a full explanation of how ES6 Modules work in my other article: Webpack 4 course – part one. Entry, output, and ES6 modules.

File System

The fs module gives us an API to interact with the file system, for example, to read, create and delete files. All operations have synchronous and asynchronous forms, but it is heavily recommended to use asynchronous functions for better performance.

The asynchronous function always takes a callback as its last argument. Let’s create our first file using a TypeScript Node.js script.


To use the File System module in TypeScript, we first need to import it. Since it created with CommonJS style of exports, we can require the whole module with  .

The first argument of the writeFile function is the path of the file and the second one is the content of it.

Using callbacks might not be something you want here. With the help of a built-in utility called promisify, we can change the writeFile function in a way that it returns a promise.

To recreate some of the bash functionalities, let’s pass additional arguments to our script using process.argv. We start with an elementary version of the touch script that creates an empty file:



To add additional arguments to an npm script, we need to prefix them with .

Thanks to all the code above, the command creates an empty file.


The second function that we implement is “cat.” In our simple implementation, it can read a file.


The command above reads the file that is under that path. The second argument of the readFile method is an object with additional options. We use it to define the encoding of a file. Without it, the readFile function results with a Buffer.

The File System can do much more, and we cover features like streams and the file descriptors in the upcoming parts of the series.


In this article, we covered the very basics of TypeScript Node.js. It included how the modules work, what is the global object, the basics of the file system and how to pass additional arguments when running a script in Node.js TypeScript. There are many more topics to cover, so stay tuned!

Series NavigationNode.js TypeScript #2. The synchronous nature of the EventEmitter >>
Notify of
Newest Most Voted
Inline Feedbacks
View all comments
a b
a b
5 years ago

Just stumbled upon this series. Working my way though it now great work 🙂

Muco Tresor
Muco Tresor
5 years ago

Thank you with your articles really helped me to understand nodejs please keep it up I appreciate the way you explain things I’m kind of person who really want to understand things on low level thank you so much

3 years ago

Excellent and very detailed article. I’ve been working with Node and Typescript for over a year and I learned a few new things here. I’ll definitely read the rest of the series.

An alternative way of gtting promised-based fs utils is:
import { promises as fs } from ‘fs’

I suspect it uses promisify too…

3 years ago

Thanks, learning a lot, after this, I am moving to mastering nest js

tornike buchukuri
tornike buchukuri
2 years ago

really insightful article, learned many things.