# Setting Up a Node.js, TypeScript, and Express Project

> Set up a Node.js, TypeScript, and Express project with this interactive guide. Learn installation, configuration, and running your server efficiently.

By Harshal Ranjhani · [HTML version](https://harshalranjhani.in/blog/setting-up-a-nodejs-typescript-and-express-project)

Node.js is a popular runtime environment for building server-side applications. It allows you to write JavaScript code that runs on the server, making it easy to build scalable and performant applications. TypeScript, a superset of JavaScript, adds static typing to the language, enhancing error detection and code maintainability. Express, a minimal and flexible Node.js web application framework, offers a robust set of features for building web and mobile applications. In this tutorial, we'll walk through how to set up a Node.js, TypeScript, and Express project from scratch.

## Why Node.js, TypeScript, and Express?

Before we jump into setting up our project, let's take a moment to understand why Node.js, TypeScript, and Express are a great combination for building web applications.

- **Node.js**: Node.js is fast, lightweight, and scalable, making it a great choice for building server-side applications.

- **Typescript**: Adds type safety to JavaScript, making your code more predictable and easier to debug.

- **Express**: A minimal and flexible Node.js web application framework that provides a robust set of features for web and mobile applications.

## Prerequisites

To get started, make sure you have Node.js and npm (Node Package Manager) installed on your machine. You can verify this by running:

```bash
node -v
npm -v
```

If you don't have it installed, head over to the [Node.js website](https://nodejs.org/en) and install it.

## Get Coding

### Initialize your project

- Create your project folder and enter into it by running:

```bash
mkdir node-typescript-express
cd node-typescript-express
```

- Next, initialize Node.js to add a `package.json` file by running:

```bash
npm init -y
```

### Install essential packages

Now let's install a few npm packages that we'll need to build this project:

```bash
npm install express
npm install -D typescript @types/node @types/express ts-node nodemon
```

This installs Express and TypeScript essentials. We’ve used the `-D` flag for `typescript`, `@types/node`, `@types/express`, `ts-node`, and `nodemon` because these are developer dependencies, meaning they’re only needed during development.

### Configuring typescript

Next, we'll configure typescript. Create a `tsconfig.json` file in the project's root folder by running:

```bash
npx tsc --init
```

Now, let’s adjust a few settings inside `tsconfig.json`:

```bash
{
  "compilerOptions": {
    "target": "ES6",
    "module": "commonjs",
    "strict": true,
    "esModuleInterop": true,
    "outDir": "./dist"
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules"]
}
```

These options specify that we’ll compile to ES6, use CommonJS modules, and output our files into a `dist` folder.

### Using a structure for our project

- Create a `src` folder in the root directory to hold your TypeScript files:

```bash
mkdir src
```

- Inside `src`, create an `index.ts` file. This will be our entry point.

### Writing the Server Code

Open `src/index.ts` and set up a simple Express server:

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

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

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

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

Here, we import Express, define a basic route for the root path (`/`), and start the server on the specified port.

**What’s Happening Here?**

- `app.get` defines a GET route for our root URL.
- `req` and `res` are typed automatically using TypeScript, making it clear what kind of objects we’re working with.
- The server runs on `http://localhost:3000` (or another port if specified in the environment).

### Configure Nodemon for Development

Instead of manually restarting the server each time we make a change, we can use Nodemon.

In `package.json`, update the `scripts` section:

```json
"scripts": {
  "start": "node dist/index.js",
  "dev": "nodemon --exec ts-node src/index.ts"
}
```

- `start` runs the compiled Javascript in production mode.
- `dev` runs the server in development mode with `ts-node` automatically restarting whenever any changes are made.

### Running our project

Let's test the sample endpoint we just created!

Run the following in your terminal while being in the project folder:

```bash
npm run dev
```

You should see a message in the terminal like: `Server is running on http://localhost:3000`. Open your browser and go to `http://localhost:3000` to see "Hello, TypeScript with Express!" displayed.

### Adding Routes and Controllers

Let's make our server more dynamic by adding more routes and controllers.

- Create a `routes` folder inside `src`.

```bash
mkdir src/routes
```

- Create a new file in `src/routes` called `userRoutes.ts`. This will define routes related to user actions.

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

const router = Router();

router.get('/users', (req: Request, res: Response) => {
  res.send('List of users');
});

export default router;
```

- Modify `index.ts` to use this new route:

```typescript
import express, { Request, Response } from 'express';
import userRoutes from './routes/userRoutes';

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

app.use('/api', userRoutes);

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

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

**What's happening here?**

- In the `userRoutes.ts` file, we're creating a new router using `express.Router()` and defining a route for `/users`.
- In `index.ts`, we're importing the `userRoutes` and using it with the `/api` prefix.
- This means that the `/users` route will be available at `http://localhost:3000/api/users`.

### Adding middlewares

Middlewares are functions that have access to the request and response objects and can modify them. Let's add a simple logging middleware to log the request method and path.

- Create a `middleware` folder.

```bash
mkdir src/middleware
```

- Create a new file in `src/middleware` called `logger.ts`.

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

const logger = (req: Request, res: Response, next: NextFunction) => {
  console.log(`${req.method} ${req.path}`);
  next();
};

export default logger;
```

- Update `index.ts` to use this middleware:

```typescript
import express, { Request, Response } from 'express';
import userRoutes from './routes/userRoutes';
import logger from './middleware/logger';

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

app.use(logger);
app.use('/api', userRoutes);

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

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

**What's happening here?**

- In the `logger.ts` file, we're defining a middleware function that logs the request method and path.
- In `index.ts`, we're importing the `logger` middleware and using it with `app.use()` to apply it to all routes.
- `app.use()` is used to mount the middleware function on the specified path.

## Conclusion

This setup gives you a structured, scalable project with Node.js, TypeScript, and Express. Here’s a quick recap of what we covered:

- Project setup and dependency installation.
- TypeScript configuration.
- A basic Express server setup.
- Organized routes and middleware.

Now you’re ready to expand on this setup, whether that means adding database connectivity, more detailed routes, or additional middleware for error handling. Enjoy building with this efficient and type-safe setup!

Last updated on October 28, 2024
