Learn how to validate user input in your Node.js application using Express Validator the right way—clean, maintainable, and scalable.
✅ Why Request Validation Matters
In real-world applications, you must validate user input to:
- 
Ensure correct data is received. 
- 
Prevent server crashes or database errors. 
- 
Enhance user experience with meaningful error messages. 
🗂 Step 1: Update the User Model
Let’s define a complete schema for our User model that includes validation requirements like required fields and default timestamps.
src/models/User.ts
    import * as mongoose from ‘mongoose’;
import { model } from ‘mongoose’;
const userSchema = new mongoose.Schema({
email: { type: String, required: true },
password: { type: String, required: true },
username: { type: String, required: true },
created_at: { type: Date, default: new Date(), required: true },
updated_at: { type: Date, default: new Date(), required: true }
});
export default model(‘users’, userSchema);
    🧪 Step 2: Bad Approach – Manual Validation (NOT RECOMMENDED)
Here’s an example of manual validation in the controller. It works but becomes messy and repetitive as your app grows.
UserController.ts
    export class UserController {
static signup(req, res, next) {
const { username, email, password } = req.body;
if (!username) return next(new Error(‘Username is required’));
if (!email) return next(new Error(‘Email is required’));
if (!password) return next(new Error(‘Password is required’));
// Save user logic here…
}
}
    ❌ Problem:
- 
Violates DRY principle (Don’t Repeat Yourself). 
- 
Clutters your controller. 
- 
Not scalable for larger forms. 
✅ Step 3: Install Express Validator
Let’s use a better approach.
Run in terminal:
npm install –save express-validator
🧱 Step 4: Create a Validator Layer
We’ll now create a validators folder and define rules for user registration.
src/validators/UserValidator.ts
    import { body } from ‘express-validator’;
export class UserValidators {
static signup() {
return [
body(‘username’, ‘Username is required’).isString(),
body(’email’, ‘Valid email is required’).isEmail(),
body(‘password’, ‘Password must be at least 6 characters long’).isLength({ min: 6 }),
];
}
}
    🎯 You can even add custom validation using
.custom()if needed later.
🔁 Step 5: Connect Validator to Router
Now we apply these validation rules before the controller logic runs.
UserRouter.ts
    import { UserValidators } from ‘../validators/UserValidator’;
import { UserController } from ‘../controllers/UserController’;
getRoutes() {
this.router.post(‘/signup’, UserValidators.signup(), UserController.signup);
}
    🧠 Step 6: Handle Validation Results in Controller
Finally, in the controller, check if validation failed using validationResult.
UserController.ts
    import { validationResult } from ‘express-validator’;
import User from ‘../models/User’;
export class UserController {
static signup(req, res, next) {
const errors = validationResult(req);
if (!errors.isEmpty()) {
const firstError = errors.array()[0].msg;
return next(new Error(firstError));
}
const { username, email, password } = req.body;
const newUser = new User({ username, email, password });
newUser.save()
.then(user => res.status(201).json(user))
.catch(err => next(err));
}
}
    ✅ Final Test
Use Postman:
- 
POST http://localhost:5000/api/user/signup
- 
Body: x-www-form-urlencoded- 
username: testuser 
- 
email: [email protected] 
- 
password: secret123 
 
- 
You’ll receive validation errors if any fields are missing or invalid.
🧩 Summary
| Step | Description | 
|---|---|
| 1️⃣ | Define schema with required fields | 
| 2️⃣ | Avoid manual validation in controller | 
| 3️⃣ | Use Express Validator for clean rules | 
| 4️⃣ | Centralize all validation in a validator file | 
| 5️⃣ | Handle errors using validationResult | 
| 6️⃣ | Return readable error messages | 
