
Express + TypeScript - Project Configuration
Introduction
This post describes a simple way to start working with TypeScript and Node, specifically with its Express framework. In this post, we will create a simple boilerplate application, which will be expanded with more advanced features in subsequent articles. I will discuss project configuration, application structure, database integration, and more.
This post, like the others in this series, contains the complete discussed code in the GitHub repository.
- Express + TypeScript - Project Configuration
- Express + TypeScript - ESLint and Prettier
- Express + TypeScript - CRUD Boilerplate
- Express + TypeScript - Application Structure
- Express + TypeScript - MongoDB Configuration
- Express + TypeScript - Request Validation with Joi
- Express + TypeScript - Application Middleware
Why?
Express.JS
Express is one of the most popular Node.js frameworks for writing backend applications. It is simple, minimalist, and imposes very few restrictions on the developer. The application structure can be almost any design, and the framework does not enforce any pattern. However, the internet is full of best practices and application development patterns.
Express is great for building REST APIs, CRUD applications, and integrating with various databases. The simple application created in this and subsequent articles will utilize the framework's simplicity and flexibility, as well as the richness of various extensions available for Express.
When we hear Express.JS, we often think of a REST API written in JavaScript. Aware of JavaScript's limitations due to the lack of static typing but still wanting to use a simple, well-proven framework that allows for extensive customization, I decided to write an application using TypeScript. As we will soon see, the framework and language work together excellently!
Getting Started
The first step should be to ensure that Node and NPM are installed on your system.
node -v
npm -v
Next, I navigate to the directory where I want to start the project. In the chosen folder, as with any Node.js project, I begin by initializing the project. The -y flag skips all questions asked by the CLI and fills them with defaults.
npm init -y
Alongside the newly created package.json file, I create a /src folder and an index.js file inside it, which will be the application's entry file.
In package.json, all dependencies used in the project are recorded. Apart from dependencies, it also contains basic project information. Here, I focus only on preparing a starter for later use in other applications. First, I change the "main" field from index.js to src/index.js according to the folder structure I just created.
{
"name": "express-ts",
"version": "1.0.0",
"description": "",
"main": "src/index.js",
"type": "module",
"scripts": {
"test": "echo "Error: no test specified" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC"
}
Now, to demonstrate that the application works, without focusing on TypeScript and Express features yet, I fill src/index.js with the simplest possible "server", which only listens on localhost:5000/ and returns "Hello World!". The first line imports express using ES modules, enabled by setting "type": "module" in package.json.
import express from "express";
const app = express();
app.get("/", (req, res) => {
res.send("Hello World!");
});
app.listen(5000, () => {
console.log("Server started on port 5000!");
});
To run the service, I need to install its dependency, the Express framework.
npm i express
After installation, I can start the application from the terminal within the project directory:
node src/index.js
The terminal will show a message that the application has started on port 5000. Opening http://localhost:5000 in a browser will display "Hello world!".
Initializing TypeScript
To use TypeScript in the application, I install it as a dev dependency along with useful type declarations for Node and Express.
npm i -D typescript @types/express @types/node
Next, I initialize TypeScript in the project:
npx tsc --init
This generates a tsconfig.json file, which defines how TypeScript should compile the project. Important settings include:
{
"compilerOptions": {
"rootDir": "./src",
"outDir": "./dist",
"target": "es2020",
"module": "commonjs",
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"strict": true,
"skipLibCheck": true
}
}
Now, I rename src/index.js to src/index.ts and update its contents:
import express, { Request, Response } from "express";
const app = express();
app.get("/", (req: Request, res: Response) => {
res.send("Hello World!");
});
app.listen(5000, () => {
console.log("Server started on port 5000!");
});
I can now compile the TypeScript project using:
npx tsc
Then, I run the generated JavaScript file:
node dist/index.js
Automating Build & Restart
I install nodemon and ts-node for automatic rebuild and restart on changes:
npm i -D nodemon ts-node
Then, I add this script to package.json:
"start:dev": "nodemon src/index.ts"
Now, running npm run start:dev will watch for changes and restart the server automatically.
Conclusion
This boilerplate serves as a foundation for more advanced projects with Express and TypeScript, ensuring better code clarity, type safety, and optimized production builds. The complete code is available in the GitHub repository.