Introduction to Express.js with TypeScript: Key Features

In this article, we will explore what Express.js with TypeScript is, why it’s widely used, how to install it, and its key features with practical examples.

What is Express.js?

Express.js is a lightweight and powerful framework for Node.js that helps you build web applications and APIs quickly and efficiently. If you’re new to backend development, think of Express as a tool that simplifies how your server handles requests and responses. Its flexibility allows you to create anything from basic websites to advanced APIs for complex applications. With features for managing HTTP requests, middleware, and routing, it’s a must-have for scalable backend systems.

Why Use It?

  • Simplicity: Easy to learn and configure.
  • Speed: High performance due to its lightweight nature.
  • Flexibility: Extendable functionalities via middleware.
  • Community and Support: Large ecosystem and extensive documentation.
  • Ideal for REST APIs: Perfect for building scalable and modular backends.
  • Database Compatibility: Easily integrates with MongoDB, MySQL, PostgreSQL, and other databases.

Installation and Setup Express.js with TypeScript

To get started with Express, you need to have Node.js installed. Then, follow these steps:

1. Initialize the project

mkdir my-express-app

Navigate to the project directory:

cd my-express-app

Initialize a new Node.js project with a pre-configured package.json file:

npm init -y

2. Install Express.js and TypeScript

To use Express with TypeScript, install the required packages:

npm install express @types/express typescript ts-node

Initialize TypeScript with the command:

npx tsc --init

This will create a TypeScript configuration file.

npm install express

3. Create a Basic Server Express.js with TypeScript

Create a file index.ts and add the following code:

import express, { Request, Response } from 'express';

const app = express();
const PORT = 3000;

app.get('/', (req: Request, res: Response) => {
    res.send('Hello, Express with TypeScript!');
});

app.listen(PORT, () => {
    console.log(`Server running on http://localhost:${PORT}`);
});

Start the server with:

ts-node index.ts

Now open your browser at http://localhost:3000 to see the result.


Key Features of Express.js

1. Routing

Express allows easy management of routes for APIs and web pages.

Use Case: User API

To manage user information, we can create the following routes:

app.get('/users', (req: Request, res: Response) => {
    res.json([{ id: 1, name: 'Mario' }, { id: 2, name: 'Luigi' }]);
});

app.get('/users/:id', (req: Request, res: Response) => {
    res.json({ id: req.params.id, name: 'Mario' });
});

Accessing http://localhost:3000/users will return a list of users.


2. Middleware

Middleware functions are executed during an HTTP request lifecycle. They can modify the request, response, or pass control to other functions. Express uses middleware for authentication, logging, data parsing, error handling, and more.

⚠️ Note: To ensure middleware execution, it is crucial to include next() in both the middleware function and the endpoints being tracked. Example:

app.use((req: Request, res: Response, next: NextFunction) => {
    console.log(`Request: ${req.method} ${req.url}`);
    next();
});

To properly pass execution to middleware, use next() in endpoints:

app.get('/users/:id', (req: Request, res: Response, next: NextFunction) => {
    res.json({ id: req.params.id, name: 'Mario' });
    next();
});

3. JSON and Data Parsing

Express makes it easy to handle incoming data, such as JSON sent from a client.

Use Case: Receiving JSON Data from a Client

If a client sends JSON data to a REST API, we can handle it with Express.

app.use(express.json()); // TypeScript automatically handles this
app.post('/data', (req: Request, res: Response) => {
    console.log('Received data:', req.body);
    res.send(`Received: ${JSON.stringify(req.body)}`);
});

Example client request using fetch in JavaScript:

fetch('http://localhost:3000/data', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ name: 'Mario', age: 30 })
})
.then(response => response.text())
.then(data => console.log(data));

This allows structured data exchange between client and server.


4. Static File Hosting

You can make static files like images, HTML, and CSS available. To do this, create a public folder in the project’s root directory and place the files you want to expose inside it.

Use Case: Exposing an HTML Page

Create a public folder and add an index.html file inside it:

<!-- public/index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Static Page</title>
</head>
<body>
    <h1>Welcome to Express with TypeScript!</h1>
</body>
</html>

Set up Express to indicate the directory where the file is located:

app.use(express.static('public'));

Now, by visiting http://localhost:3000/index.html, you will be able to see the static page.


5. Error Handling

Express makes it easy to handle custom errors. We can also create an endpoint that intentionally generates an error to test the error-handling middleware.

Use Case: Endpoint that Generates an Error

We can create an endpoint that simulates an error:

app.get('/data_with_error', (req: Request, res: Response) => {
    throw new Error('Test error');
});

Use Case: Global Error Middleware

app.use((err: Error, req: Request, res: Response) => {
    console.error(err.stack);
    res.status(500).json({ message: 'Something went wrong!', error: err.message });
});

This middleware intercepts errors and prevents server crashes.


6. Connecting to a Database

Express does not include an ORM, but it can be easily integrated with MongoDB, PostgreSQL, and other databases.

Use Case: Connecting to MongoDB with Mongoose

To use MongoDB, install Mongoose:

npm install mongoose

Then, configure the connection:

import mongoose from 'mongoose';

mongoose.connect('mongodb://localhost:27017/mydb', { useNewUrlParser: true, useUnifiedTopology: true })
    .then(() => console.log('MongoDB Connected'))
    .catch(err => console.error('MongoDB connection error:', err));

Now, you can define models and interact with the database directly in your Express backend.

Alternative Database Options

If you prefer an alternative approach, consider other ORM libraries:

  • Sequelize: A great option for relational databases like PostgreSQL, MySQL, and SQLite.
  • Knex.js: A flexible query builder supporting various SQL databases.

Example: Connecting to PostgreSQL with Sequelize:

import { Sequelize } from 'sequelize';
const sequelize = new Sequelize('postgres://user:password@localhost:5432/mydb');

sequelize.authenticate()
    .then(() => console.log('PostgreSQL Connected'))
    .catch(err => console.error('Error connecting to PostgreSQL:', err));

Choose the ORM or query builder that best suits your project.

Conclusion

This article is not an in-depth guide to Express.js but a general overview to help you quickly understand its added value and main functionalities. The goal is to give you a clear idea of what Express can do and how to start using it. For more details and advanced topics, refer to the additional resources below.

Additional Resources

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top