Route Parameters

⭐ Interview Importance: LOW
⏱️ Revision Time: 10 min

Route parameters allow you to capture dynamic values from the URL path.

Overview

Routes with static paths won’t work when you need to accept dynamic data as part of the URL (e.g., fetching a specific user by ID: GET /users/1).

In NestJS, you define route parameters by adding a colon (:) before the parameter name in the route string. You then extract that parameter in your method signature using the @Param() decorator.

Key Concepts

  • Definition: Define parameters in the route path using :paramName (e.g., @Get(':id')).
  • Extraction: Use @Param('paramName') to inject the value into your method arguments.
  • Extracting all parameters: Using @Param() without a string key injects an object containing all route parameters.

Code Examples

Extracting a Specific Parameter

import { Controller, Get, Param } from '@nestjs/common';

@Controller('users')
export class UsersController {
  
  // Route: GET /users/123
  @Get(':id')
  findOne(@Param('id') id: string) {
    // Note: 'id' is a string by default, even if you passed a number in the URL!
    return `This action returns user #${id}`;
  }
}

Multiple Parameters

// Route: GET /users/123/posts/456
@Get(':userId/posts/:postId')
findUserPost(
  @Param('userId') userId: string, 
  @Param('postId') postId: string
) {
  return `Returning post #${postId} for user #${userId}`;
}

Extracting All Parameters as an Object

While it’s better practice to extract them explicitly, you can get all of them at once.

@Get(':userId/posts/:postId')
findAllParams(@Param() params: Record<string, string>) {
  return `User: ${params.userId}, Post: ${params.postId}`;
}

Using Pipes with Route Parameters

Because parameters extracted from the URL are always strings, it is highly recommended to use built-in Pipes to transform and validate them.

import { Controller, Get, Param, ParseIntPipe, ParseUUIDPipe } from '@nestjs/common';

@Controller('users')
export class UsersController {
  
  // Transform the string '1' into the number 1, throwing a 400 if it's not a number
  @Get(':id')
  findOne(@Param('id', ParseIntPipe) id: number) {
    return this.usersService.findOne(id); // id is typed as a number!
  }

  // Ensure the parameter is a valid UUID
  @Get('profile/:uuid')
  getProfile(@Param('uuid', ParseUUIDPipe) uuid: string) {
    return this.usersService.findByUuid(uuid);
  }
}

Best Practices

  • Always use Transformation Pipes: If your database expects a number or a UUID, always use ParseIntPipe or ParseUUIDPipe in the @Param() decorator. This ensures type safety and automatically handles 400 Bad Request errors for invalid inputs.
  • Explicit Extraction: Prefer @Param('id') over @Param(). Extracting exactly what you need makes the method signature self-documenting and easier to test.