Skip to content

05. Validation & Transformation

1. The Vanilla Mechanics

Data validation ensures that the input to your API is correct and safe. In Express, this is often done using manual checks or libraries like Joi or Zod.

Concept: Manual Validation

  • Type Checking: Ensuring a field is a string or number.
  • Business Rules: Ensuring a field is not empty or within a specific range.

The β€œRaw” Implementation (Example)

app.post('/users', (req, res) => {
  const { email, age } = req.body;

  // Manual validation logic (Vanilla)
  if (!email || !email.includes('@')) {
    return res.status(400).send('Invalid email');
  }
  if (typeof age !== 'number' || age < 18) {
    return res.status(400).send('Age must be a number >= 18');
  }

  // Business logic...
  res.send('User created');
});

Challenges:

  • Duplication: Validation logic is often repeated across routes.
  • Clutter: Route handlers become bloated with validation code.
  • Transformation: Manually casting a string ID from a URL to a number (parseInt) is error-prone.

2. The NestJS Abstraction

NestJS uses Pipes to handle validation and transformation in a unified way.

Key Advantages:

  • ValidationPipe: Integrated with class-validator and class-transformer for declarative validation.
  • Global Pipes: Apply validation to every route in your application with a single line of code.
  • Automatic Transformation: Cast incoming types automatically (e.g., string to number).

The NestJS Implementation:

import { IsEmail, IsInt, Min } from 'class-validator';

// 1. Define a Data Transfer Object (DTO)
export class CreateUserDto {
  @IsEmail()
  email: string;

  @IsInt()
  @Min(18)
  age: number;
}

@Post()
create(@Body(new ValidationPipe()) dto: CreateUserDto) {
  // At this point, the data is GUARANTEED to be valid!
  return 'User created';
}

3. Engineering Labs

  • Lab 5.1: Write a validation function in an Express handler that checks for a valid username, password, and age. Return a detailed error object.
  • Lab 5.2: Re-implement the validation using a NestJS DTO and the ValidationPipe. Observe how NestJS automatically generates detailed error responses.