DEV Community

Cover image for Validating numeric query parameters in NestJS

Validating numeric query parameters in NestJS

Krzysztof Szala on April 12, 2021

Another day, another short article. Today we will focus on validation of numeric query parameters. Everyone values his/her time, so here is TL;DR:...
Collapse
 
mynameisdu profile image

Good article. I read all your articles on validation. And I have an ideas. I think if want to validate numeric,should use ParseIntPipe, it will transform and if it isn't a number it will throw error

Collapse
 
avantar profile image
Krzysztof Szala

The main point of my approach is to have the whole validation process in one place :)

Collapse
 
begalievn profile image
Nursultan Begaliev

Thank you)

Collapse
 
sebytab profile image
sebytab

Just a little issue with this way of transform & validate query params: try @Type(() => Boolean), you'll have to use @Transform and do it yourself.

Collapse
 
avantar profile image
Krzysztof Szala

Hi! Thank you for your comment. I'm not sure what do you want to achive with your code example. Could you give me an example of URL and final object with values you want to get? Regards!

Collapse
 
sebytab profile image
sebytab

Just try with some boolean param, or even an array.

export class FilterQuery {
@IsOptional()
@IsBoolean()
@Type(() => Boolean)
prova?: boolean
}

Setting 'prova' as 'false' it will cast it to true. As you said, those query params are just strings that must be serialized first in some way. So, in some cases like Number it just works but in others it follows JS conversion rules... I partially solved it doing using @Transform instead of @Type and looking Nestjs parse implementations github.com/nestjs/nest/tree/99ee3f...

Thread Thread
 
avantar profile image
Krzysztof Szala

You are totally right! And this is the reason why this article is titled “Validating numeric query params” 😁 I think it’s the most common issue Nest users encounter (at least in my experience).

For array of values in query params I use (exactly as you said) Transform decorator from class-transform package. For bools I prefer to pass just boolean in numeric form (0 or 1) or (depends on context) simple string like yes/no. But I avoid true/false, because as you noted – it can result with some false positives.

Anyway, thank you for your comment, I’m sure somebody finds it helpful! Cheers!

Thread Thread
 
sebytab profile image
sebytab

Thank you for the article, it's my first time with Nestjs and I was looking for how to parse & validate params declaratively and without too many hustles. I hadn't noticed "numeric" in the title, sorry 😅
How do you manage arrays, i.e. numeric[] ? At the moment I use ParseArray (that also is the only Parse* function that can handle natively missing query params)

Thread Thread
 
avantar profile image
Krzysztof Szala

I've struggled with arrays a lot, and ended up with some like this. I'm not very proud of it, but it works for me.

I decorate expected field with:

@IsArray()
@Transform(({ value }) => (value ? Transformation.mapStringToNumber(value) : undefined))
categories: number[];
Enter fullscreen mode Exit fullscreen mode

And here is mapStringToNumber implementation:

export class Transformation {
  static mapStringToNumber(value: string | string[]): number[] | undefined {
    const explodedValues = typeof value === 'string' ? value.split(',') : value;
    const filteredValues = explodedValues.filter(Number).map(Number);

    return filteredValues.length > 0 ? filteredValues : undefined;
  }
}
Enter fullscreen mode Exit fullscreen mode

It allows me to pass array of numbers and just string with numbers separated with commas as well. It also cleans up non-numeric values. So, when you pass e.g. categories=1,a,2, you will get an array of [1,2].

I'm not the biggest fan of using extra pipes for validating. I rather try to keep my validation in one place (in validation class with class-validator in this case).

Collapse
 
brucexu_eth profile image
Bruce Xu

If the example is not working on your code, please check if you enabled ValidationPipe. Find more here: docs.nestjs.com/techniques/validat...

Collapse
 
danielwong2268 profile image
Daniel Wong

Furthermore, I discovered it is required to pass in the following options to ValidationPipe

    new ValidationPipe({
      transform: true,
      transformOptions: {
        enableImplicitConversion: true,
      },
    }),
Enter fullscreen mode Exit fullscreen mode

else the type of the query param value at runtime will still be string, even though it may pass the class-validator validations.

Collapse
 
beyond88 profile image
Mohiuddin Abdul Kader

Information

Collapse
 
amine_bcode profile image
AMINE BK

It would be great if we could do something like :
import IsEmail from 'class-validator'
@Query('email', IsEmail) email:string

Collapse
 
akojimsg profile image
EI Akoji

Awesome article

Collapse
 
tobils profile image
ade suhada

awesome, this is just working properly .. thanks buddy

Collapse
 
avantar profile image
Krzysztof Szala

Nice to hear that!

Collapse
 
wottery profile image
lvlei

tk u gs