Login Register
Code2night
  • Home
  • Blog Archive
  • Learn
    • Tutorials
    • Videos
  • Interview Q&A
  • Languages
    • Angular
    • Angular js
    • Asp.net Core
    • C
    • C#
    • DotNet
    • HTML/CSS
    • Java
    • JavaScript
    • Node.js
    • Python
    • React
    • Security
    • SQL Server
    • TypeScript
  • Post Blog
  • Tools
    • JSON Beautifier
    • HTML Beautifier
    • XML Beautifier
    • CSS Beautifier
    • JS Beautifier
    • PDF Editor
    • Word Counter
    • Base64 Encode/Decode
    • Diff Checker
    • JSON to CSV
    • Password Generator
    • SEO Analyzer
    • Background Remover
  1. Home
  2. Blog
  3. TypeScript
  4. Building a REST API with TypeScript and Node.js: A Comprehensive Guide

Building a REST API with TypeScript and Node.js: A Comprehensive Guide

Date- Mar 26,2026

4

typescript node.js

Overview

TypeScript is a superset of JavaScript that adds static typing to the language, enhancing code quality and maintainability. In the context of building a REST API, TypeScript provides a robust structure that helps developers catch errors at compile time rather than runtime. This is particularly valuable in large-scale applications where managing complex data structures and APIs can become overwhelming.

Node.js, on the other hand, is a runtime environment that allows developers to execute JavaScript on the server side. This enables the creation of fast and scalable network applications. When combined, TypeScript and Node.js offer a powerful platform for developing RESTful services that are not only efficient but also easy to understand and maintain.

Real-world applications of TypeScript and Node.js REST APIs range from simple CRUD applications to complex microservices architectures. Companies like Netflix and LinkedIn use these technologies to handle millions of requests and maintain high performance, demonstrating their effectiveness in the field.

Prerequisites

  • Node.js: Make sure Node.js is installed on your machine, as it provides the runtime for executing JavaScript code on the server side.
  • NPM: Node Package Manager, which comes with Node.js, is necessary for managing project dependencies.
  • TypeScript: Familiarity with TypeScript is essential, as it will be the primary language used in this guide.
  • Basic JavaScript Knowledge: Understanding JavaScript fundamentals is crucial, as TypeScript is built on it.

Setting Up the Project

To start building a REST API with TypeScript and Node.js, the first step is to set up the project environment. This involves creating a new directory and initializing a Node.js application.

mkdir typescript-node-api
cd typescript-node-api
npm init -y

The command npm init -y creates a package.json file with default settings. Next, we need to install TypeScript and the necessary type definitions:

npm install typescript ts-node @types/node --save-dev

This command installs TypeScript, a TypeScript execution engine (ts-node), and type definitions for Node.js. After installation, initialize a TypeScript configuration file:

npx tsc --init

The above command creates a tsconfig.json file, which allows you to customize TypeScript compiler options. At this stage, ensure that the outDir and rootDir options are set appropriately:

{
"compilerOptions": {
"outDir": "./dist",
"rootDir": "./src",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true
}
}

Here, outDir specifies where the compiled JavaScript files should go, and rootDir indicates where the TypeScript source files are located.

Creating the Basic Server

Now that the project is set up, the next step is to create a basic server using Node.js and TypeScript. To do this, create a new directory called src and a file named server.ts within it:

mkdir src
touch src/server.ts

In server.ts, we will use the Express framework, which simplifies the process of building APIs. Install Express and its type definitions:

npm install express @types/express

Now, populate server.ts with the following code:

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

const app = express();
const PORT = process.env.PORT || 3000;

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

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

In this code:

  • import express, { Request, Response } from 'express'; imports the Express framework and its types for request and response objects.
  • const app = express(); initializes an instance of the Express application.
  • const PORT = process.env.PORT || 3000; sets the port for the server, defaulting to 3000 if no environment variable is set.
  • app.get('/', (req: Request, res: Response) => { ... }); defines a route handler for GET requests to the root URL, sending a simple 'Hello World!' message.
  • app.listen(PORT, () => { ... }); starts the server and logs a message to the console once it is up and running.

To run the server, execute:

npx ts-node src/server.ts

The expected output should indicate that the server is running:

Server is running on http://localhost:3000

Defining RESTful Routes

With the server in place, the next step is to define RESTful routes. REST APIs typically use standard HTTP methods such as GET, POST, PUT, and DELETE to perform CRUD operations. For this example, we will implement a simple API for managing a list of items.

First, create a new file called items.ts in the src directory:

touch src/items.ts

In items.ts, we will define the item data structure and the routes:

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

interface Item {
id: number;
name: string;
}

const items: Item[] = [];
const router = Router();

router.get('/', (req: Request, res: Response) => {
res.json(items);
});

router.post('/', (req: Request, res: Response) => {
const newItem: Item = {
id: items.length + 1,
name: req.body.name,
};
items.push(newItem);
res.status(201).json(newItem);
});

export default router;

This code defines:

  • interface Item: a TypeScript interface representing the structure of an item with an id and name.
  • const items: Item[] = [];: an array to hold the items.
  • const router = Router();: creates a new router instance for defining routes.
  • router.get('/', ...);: defines a GET route to retrieve all items.
  • router.post('/', ...);: defines a POST route to add a new item to the list.

Next, import the items.ts router in server.ts and use it:

import itemsRouter from './items';

app.use(express.json());
app.use('/api/items', itemsRouter);

Here, app.use(express.json()); is crucial as it allows the server to parse JSON request bodies. The items router is mounted on the path /api/items, allowing access to the defined routes.

With this setup, you can now test the API using tools like Postman or curl.

Handling Errors

In any API, proper error handling is essential for providing meaningful feedback to clients. In Express, middleware can be utilized for centralized error handling.

To implement error handling, create a new file called errorHandler.ts in the src directory:

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

const errorHandler = (err: Error, req: Request, res: Response, next: NextFunction) => {
console.error(err.stack);
res.status(500).send('Something broke!');
};

export default errorHandler;

This code defines an error-handling middleware function:

  • console.error(err.stack); logs the error stack to the console for debugging purposes.
  • res.status(500).send('Something broke!'); sends a 500 Internal Server Error response to the client.

Next, import and use the error handler middleware in server.ts:

import errorHandler from './errorHandler';

app.use(errorHandler);

This middleware will catch any errors that occur in the application and respond accordingly.

Edge Cases & Gotchas

When building APIs, certain edge cases and pitfalls can arise, leading to unexpected behavior. One common issue is not validating request data before processing it.

For instance, consider the following incorrect implementation:

router.post('/', (req: Request, res: Response) => {
const newItem: Item = {
id: items.length + 1,
name: req.body.name,
};
items.push(newItem);
res.status(201).json(newItem);
});

This implementation does not check if req.body.name is provided, which can lead to undefined values in the item list. The correct approach would be to validate the input:

router.post('/', (req: Request, res: Response) => {
if (!req.body.name) {
return res.status(400).send('Name is required');
}
const newItem: Item = {
id: items.length + 1,
name: req.body.name,
};
items.push(newItem);
res.status(201).json(newItem);
});

This version checks for the presence of name before creating a new item and responds with a 400 Bad Request status if it is missing.

Performance & Best Practices

To ensure optimal performance in your REST API built with TypeScript and Node.js, consider the following best practices:

  • Asynchronous Code: Use asynchronous programming patterns (e.g., async/await) to handle I/O operations efficiently.
  • Connection Pooling: If using a database, implement connection pooling to manage database connections effectively.
  • Limit Response Size: Implement pagination and limit response sizes to avoid overwhelming clients with data.
  • Use Caching: Implement caching strategies to reduce load on your server and speed up response times.

For example, using async/await in your route handlers can improve performance:

router.get('/', async (req: Request, res: Response) => {
try {
res.json(items);
} catch (error) {
next(error);
}
});

This use of async/await allows you to handle asynchronous operations cleanly and catch errors that may occur during data retrieval.

Real-World Scenario: Building a Mini-Project

To tie all these concepts together, let’s create a mini-project — a simple task manager API. This API will allow users to create, read, update, and delete tasks.

First, create a new file called tasks.ts in the src directory:

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

interface Task {
id: number;
title: string;
completed: boolean;
}

const tasks: Task[] = [];
const router = Router();

router.get('/', (req: Request, res: Response) => {
res.json(tasks);
});

router.post('/', (req: Request, res: Response) => {
const newTask: Task = {
id: tasks.length + 1,
title: req.body.title,
completed: false,
};
tasks.push(newTask);
res.status(201).json(newTask);
});

router.put('/:id', (req: Request, res: Response) => {
const task = tasks.find(t => t.id === +req.params.id);
if (!task) {
return res.status(404).send('Task not found');
}
task.completed = req.body.completed;
res.json(task);
});

router.delete('/:id', (req: Request, res: Response) => {
const index = tasks.findIndex(t => t.id === +req.params.id);
if (index === -1) {
return res.status(404).send('Task not found');
}
tasks.splice(index, 1);
res.status(204).send();
});

export default router;

This implementation includes:

  • GET /api/tasks: retrieves all tasks.
  • POST /api/tasks: creates a new task.
  • PUT /api/tasks/:id: updates the completion status of a task.
  • DELETE /api/tasks/:id: deletes a task.

Finally, update server.ts to use this new router:

import tasksRouter from './tasks';

app.use('/api/tasks', tasksRouter);

This mini-project effectively demonstrates the principles of building a REST API using TypeScript and Node.js while providing a practical use case.

Conclusion

  • TypeScript enhances the development experience by adding static typing to JavaScript, reducing runtime errors.
  • Node.js enables server-side JavaScript execution, making it possible to build scalable network applications.
  • Express simplifies API route management, allowing for a clean and organized structure.
  • Proper error handling and input validation are crucial for building reliable APIs.
  • Performance can be improved through best practices such as asynchronous programming, caching, and limiting response sizes.

Next, consider exploring advanced topics such as authentication with JWT, integrating databases with TypeORM, or deploying your API to a cloud provider.

S
Shubham Saini
Programming author at Code2Night — sharing tutorials on ASP.NET, C#, and more.
View all posts →

Related Articles

Mastering TypeScript Enums: A Deep Dive into Numeric and String Enums
Mar 26, 2026
Introduction to Angular - Getting Started with a Comprehensive Guide
Mar 26, 2026
Mastering Angular Services and Dependency Injection for Scalable Applications
Mar 25, 2026
Mastering Node.js Streams and Buffers: A Comprehensive Guide
Mar 24, 2026
Previous in TypeScript
Mastering TypeScript Utility Types: Partial, Required, Readonly, …
Next in TypeScript
Understanding TypeScript Strict Mode: Best Practices and Real-Wor…

Comments

Contents

🎯

Interview Prep

Ace your TypeScript interview with curated Q&As for all levels.

View TypeScript Interview Q&As

More in TypeScript

  • Mastering TypeScript with Angular: A Comprehensive Guide 25 views
  • Mastering Generics in TypeScript: A Comprehensive Guide 6 views
  • Understanding TypeScript Strict Mode: Best Practices and Rea… 5 views
  • Mastering Decorators in TypeScript: A Deep Dive into Decorat… 5 views
  • Mastering TypeScript Utility Types: Partial, Required, Reado… 1 views
View all TypeScript posts →

Tags

AspNet C# programming AspNet MVC c programming AspNet Core C software development tutorial MVC memory management Paypal coding coding best practices data structures programming tutorial tutorials object oriented programming Slick Slider StripeNet
Free Download for Youtube Subscribers!

First click on Subscribe Now and then subscribe the channel and come back here.
Then Click on "Verify and Download" button for download link

Subscribe Now | 1760
Download
Support Us....!

Please Subscribe to support us

Thank you for Downloading....!

Please Subscribe to support us

Continue with Downloading
Be a Member
Join Us On Whatsapp
Code2Night

A community platform for sharing programming knowledge, tutorials, and blogs. Learn, write, and grow with developers worldwide.

Panipat, Haryana, India
info@code2night.com
Quick Links
  • Home
  • Blog Archive
  • Tutorials
  • About Us
  • Contact
  • Privacy Policy
  • Terms & Conditions
  • Guest Posts
  • SEO Analyzer
Free Dev Tools
  • JSON Beautifier
  • HTML Beautifier
  • CSS Beautifier
  • JS Beautifier
  • Password Generator
  • QR Code Generator
  • Hash Generator
  • Diff Checker
  • Base64 Encode/Decode
  • Word Counter
  • SEO Analyzer
By Language
  • Angular
  • Angular js
  • Asp.net Core
  • C
  • C#
  • DotNet
  • HTML/CSS
  • Java
  • JavaScript
  • Node.js
  • Python
  • React
  • Security
  • SQL Server
  • TypeScript
© 2026 Code2Night. All Rights Reserved.
Made with for developers  |  Privacy  ·  Terms
Translate Page
We use cookies to improve your experience and analyze site traffic. By clicking Accept, you consent to our use of cookies. Privacy Policy
Accessibility
Text size
High contrast
Grayscale
Dyslexia font
Highlight links
Pause animations
Large cursor