Search code examples
typescriptvalidationnestjsdtoclass-validator

Manage optional and required fields using another field in Nestjs DTO


I want to make fields required based on another field in the DTO itself.

Currently my DTO looks like:

import { LOGIN_TYPE } from "src/utils/constants";
import { IsIn, IsNotEmpty, IsOptional } from "class-validator";

export class LoginDto {
    @IsOptional()
    phoneNumber: string

    @IsOptional()
    fcmToken: string

    @IsOptional()
    accessToken: string

    @IsOptional()
    @IsIn([LOGIN_TYPE.APPLE, LOGIN_TYPE.GOOGLE, LOGIN_TYPE.FACEBOOK, LOGIN_TYPE.PHONE_NUMBER_OTP])
    loginType: string = LOGIN_TYPE.PHONE_NUMBER_OTP;
}

But the problem is, I don'y want to make it optional blindly.

If "loginType" = PHONE_NUMBER_OTP, I want "phoneNumber" as the mandatory parameter If "loginType" = GOOGLE || APPLE || FACEBOOK, I want "accessToken" as the mandatory parameter

How can I achieve that in DTO itself.

I have used {transform: true} already. Any help or suggestion handle in another way is much appeciated! Thank you so much in advance

Tried: Making all optional but I don't wanna handle those stuffs inside my service Expectation: I want to handled this validations in DTO itself


Solution

  • You can use conditional validation:

    import { LOGIN_TYPE } from "src/utils/constants";
    import { IsIn, IsNotEmpty, IsOptional, ValidateIf } from "class-validator";
    
    export class LoginDto {
        @IsOptional()
        phoneNumber: string
    
        @IsOptional()
        fcmToken: string
    
        @ValidateIf((body) => [LOGIN_TYPE.APPLE, LOGIN_TYPE.GOOGLE, LOGIN_TYPE.FACEBOOK].includes(body.loginType))
        @IsNotEmpty()
        accessToken: string
    
        @IsOptional()
        @IsIn([LOGIN_TYPE.APPLE, LOGIN_TYPE.GOOGLE, LOGIN_TYPE.FACEBOOK, LOGIN_TYPE.PHONE_NUMBER_OTP])
        loginType: string = LOGIN_TYPE.PHONE_NUMBER_OTP;
    }
    

    The validation rules on accessToken will be ignored if the @ValidateIf() callback returns false.