>_
EngineeringNotes
Back to Additional Modules

Node.js Server with TypeScript

A comprehensive guide to building a robust backend using Express, TypeScript, and your choice of database (MongoDB or PostgreSQL).

1

Project Initialization

Start by creating a new directory and initializing your project with TypeScript and Express.

🍞 Using Bun?

If you prefer using Bun for a faster runtime and built-in package manager, check out our Monorepo guide which covers Bun initialization.

View Bun Setup →
Terminal
bash
# Create project folder
mkdir hell-prisma
cd hello-prisma

# Initialize Node.js
npm init -y

# Install Support Packages
npm install typescript tsx @types/node --save-dev

# Install Express & Utilities
npm install express dotenv
npm install -D @types/express

# Initialize TypeScript
npx tsc --init
ℹ️

ESM Support

We are using ESM (EcmaScript Modules) effectively. Update your package.json to include:

"type": "module"

Update your tsconfig.json for ESM compatibility:

tsconfig.json
json
{
  "compilerOptions": {
    "module": "ESNext",
    "moduleResolution": "bundler",
    "target": "ES2023",
    "strict": true,
    "esModuleInterop": true,
    "ignoreDeprecations": "6.0"
  }
}
2

Basic Express Setup

Create a basic server structure in src/index.ts.

src/index.ts
typescript
import express, { Request, Response } from 'express';
import dotenv from 'dotenv';

dotenv.config();

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

app.use(express.json());

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

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

Database Integration

1. Setup & Connection

Configure your .env file. Choose your provider:

MongoDB Atlas (Cloud)

Get string from "Connect" button in Atlas.

mongodb+srv://user:pass@cluster.mongodb.net/?retryWrites=true&w=majority
Local / Docker

Run: docker run -d -p 27017:27017 mongo

mongodb://localhost:27017/myapp

Install mongoose and connect:

Terminal
bash
npm install mongoose
src/db/connect.ts
typescript
import mongoose from 'mongoose';

const connectDB = async () => {
  try {
    await mongoose.connect(process.env.MONGO_URI as string);
    console.log('MongoDB Connected');
  } catch (error) {
    console.error('MongoDB connection error:', error);
    process.exit(1);
  }
};

export default connectDB;

2. User Interface & Model

Define the shape of your user document and create the model.

src/models/User.ts
typescript
import mongoose, { Schema, Document } from 'mongoose';

// 1. Create an Interface representing a document in MongoDB.
export interface IUser extends Document {
  name: string;
  email: string;
  age: number;
  password?: string; // Optional if you hash it elsewhere
}

// 2. Create a Schema corresponding to the document interface.
const UserSchema: Schema = new Schema({
  name: { type: String, required: true },
  email: { type: String, required: true, unique: true },
  age: { type: Number, required: true },
  password: { type: String, required: true },
});

// 3. Create a Model.
const User = mongoose.model<IUser>('User', UserSchema);

export default User;

3. Create User API

src/routes/user.ts
typescript
import express, { Request, Response } from 'express';
import User, { IUser } from '../models/User';

const router = express.Router();

router.post('/signup', async (req: Request, res: Response) => {
  try {
    const { name, email, age, password } = req.body;

    // Create a new user instance
    const newUser: IUser = new User({
      name,
      email,
      age,
      password
    });

    // Save to database
    await newUser.save();

    res.status(201).json({ message: 'User created successfully', user: newUser });
  } catch (error) {
    res.status(500).json({ message: 'Error creating user', error });
  }
});

export default router;
4

Final Integration

Connect everything in your src/index.ts.

src/index.ts
typescript
import express from 'express';
import dotenv from 'dotenv';
import userRoutes from './routes/user';
import connectDB from './db/connect';

dotenv.config();
const app = express();

app.use(express.json());

// Routes
app.use('/users', userRoutes);

const start = async () => {
  try {
    await connectDB();
    app.listen(3000, () => console.log('Server started on port 3000'));
  } catch (error) {
    console.error(error);
    process.exit(1);
  }
};

start();

Run your development server with tsx:

Terminal
bash
npx tsx src/index.ts