`The Importance of Validating Enum Arrays in Typescript Using Class-Validator`

Is there a way to validate an array of enums in a DTO without getting misleading error messages?

Here is an example of my DTO:

import { IsArray, IsEmail, IsEnum, IsIn, IsNotEmpty, IsString } from "class-validator";
import { UserAction, UserModule, UserRole } from "../enums";

import { ApiProperty } from "@nestjs/swagger";

export class CreateUserDto {

    @ApiProperty({ 
        example: 'e5c082ae-6760-4dbf-a69b-e01e94108c63', 
        description: 'The unique identifier of an user' 
    })
    @IsString()
    @IsNotEmpty()
    name: string;

    @ApiProperty({ 
        example: '<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="f8959980d6958d8b8c9d8a95999696b88b999588949dd69b9795">[email protected]</a>', 
        description: 'The email of an user' 
    })
    @IsString()
    @IsEmail()
    @IsNotEmpty()
    email: string;

    @ApiProperty({ 
        example: '!s3cr3t!',
        description: 'The password of an user'
    })
    @IsString()
    @IsNotEmpty()
    password: string;

    @ApiProperty({ 
        example: [UserRole.Admin, UserRole.User],
        description: 'The role of an user',
        enum: UserRole,
        isArray: false
    })
    @IsIn([UserRole.Admin, UserRole.User])
    @IsEnum(UserRole)
    @IsNotEmpty()
    userRole: UserRole;

    @ApiProperty({ 
        example: [UserModule.Dashboard, UserModule.AccountManagement, UserModule.ReportManagement],
        description: 'The module of an user',
        enum: UserModule,
        isArray: true
    })
    @IsIn([UserModule.Dashboard, UserModule.AccountManagement, UserModule.ReportManagement])
    @IsEnum(UserModule, { each: true })
    @IsNotEmpty()
    userModules: UserModule[];

    @ApiProperty({
        example: [UserAction.Manage, UserAction.Create, UserAction.Read, UserAction.Update, UserAction.Delete],
        description: 'The action of an user',
        enum: UserAction,
    })
    @IsIn([UserAction.Manage, UserAction.Create, UserAction.Read, UserAction.Update, UserAction.Delete])
    @IsEnum(UserAction, { each: true })
    @IsArray()
    @IsNotEmpty()
    userActions: UserAction[];
}

This is how the POSTMAN request body looks like:

{
    "name": "David",
    "email": "<a href=\"/cdn-cgi/l/email-protection\" class=\"__cf_email__\" data-cfemail=\"2e4a4f58474a6e49434f4742004d41443\">[email protected]</a>",
    "password": "123456",
    "userRole": "admin",
    "userModules": [ "dashboard", "account-management" ],
    "userActions": [ "manage" ]
}

But when I make this POSTMAN request, I receive the following response:

{
    "statusCode": 400,
    "message": [
        "userModules must be one of the following values: dashboard, account-management, report-management",
        "userActions must be one of the following values: manage, create, read, update, delete"
    ],
    "error": "Bad Request"
}

I don't understand why it's asking for specific values when they are clearly defined. I even tried implementing my own ValidatorConstraintInterface, but with no luck.

Answer №1

@IsEnum(UserRole, { each: true })

That's the way it's supposed to function.

Answer №2

IsEnum(each: true) and IsIn are in conflict with each other; while IsEnum(each: true) is designed for arrays, IsIn is intended for single values (refer to the documentation). It is recommended to remove IsIn.

Furthermore, IsNotEmpty should only be used with strings; for other data types, consider using IsDefined. Use @ArrayNotEmpty for non-empty arrays.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Issue with debounce function failure in handling onChange event for a controlled input field

Currently, I am experimenting with the Material UI React framework. I recently moved my application to Material UI using TypeScript. However, I seem to be encountering an issue with the debounce function when used in the onChange handler for input fields. ...

Exploring Typescript's type narrowing capabilities through destructuring

This code snippet is encountering errors: type Example = { x: true, y: null, z: null } | { x: false, y: Error, z: null } | { x: false, y: null, z: { val: number} } function getExample(): Example { return { x: false, y: null, z: { val ...

Retrieve the Document ID from Firebase

I'm currently exploring the functionality of Firebase and enhancing my workflow with "react-firebase-hooks". Is there a way for me to retrieve both the doc id and doc data simultaneously and pass them as props? Currently, I am only able to access the ...

Error encountered in app.module.ts file of Angular 2 application

My friends and I are working on a big school project, creating a cool web app. Suddenly, I encountered some errors in my app.module.ts file that I haven't seen before. It's strange because they are showing up out of nowhere! The error: Error:( ...

Navigating API data conversion on the frontend using Object-Oriented Programming

Currently, I am facing a challenge while developing the frontend of a web application using TypeScript. The dilemma revolves around efficiently converting a data object from an API response into a format suitable for the application. Let's consider r ...

Struggling to retrieve object values through useContext? Consider implementing useReducer in conjunction with useContext for more efficient state management

I'm facing an issue while trying to access my dispatch functions and states from the useContext. Strangely, when I attempt to destructure the context object in order to access them directly, I receive an error message stating that it does not exist (E ...

Navigating from a Card to a new View in Angular

I am currently developing a project using Angular (latest version). Within my application, I have the functionality to dynamically generate bootstrap cards from an Order Array and display them in my "Order-Item-Component through its respective template. ...

Tips for Modifying the currentUrl identifier in Angular 2

I am trying to change the ID property of my currentUrl object within my component. My goal is for the ID to update and then fetch the corresponding data based on that ID. However, I keep encountering this error message: "Cannot assign to read only propert ...

What steps can be taken to retrieve error.data from RTK Query while utilizing typescript?

When I log error to the console, this is what I see: { status: 401, data: "Invalid password" } If I attempt to log error.data, an error occurs: The "data" property does not exist in the "FetchBaseQueryError|SerializedErr ...

The Ultimate Guide to Uploading Files to Google Cloud Storage with Nestjs

After researching online for guidance on uploading a file to Google Storage with NestJS, I came up empty-handed. Can anyone lend a hand? -What's the process of connecting Google Cloud with a NestJS server? -How can a file be uploaded from the client ...

The Angular2 Router encounters an issue with the URL when it contains the "&

Ever since updating to the latest version of angular v4.3.2, I've encountered an issue where all my URLs break at the & value. For instance, I have a route /:value from which I need to retrieve the value: http://localhost:4200/one&two Inst ...

reading an array of objects using typescript

Trying to retrieve an object from an array called pVal. pVal is the array that includes objects. I am attempting to obtain the value of "group" based on the id provided. For instance, if the id is equal to 1, it should display "VKC". Any assistance woul ...

Creating a unique Elastic IP address for a single EC2 instance with the AWS CDK

I'm having an issue with my AWS CDK Stack where multiple Elastic IPs are being created for each public subnet in my VPC instead of just one. I only want one Elastic IP to be associated with a single EC2 instance. My simplified code snippet is as foll ...

Transitioning a JavaScriptIonicAngular 1 application to TypescriptIonic 2Angular 2 application

I am currently in the process of transitioning an App from JavaScript\Ionic\Angular1 to Typescript\Ionic2\Angular2 one file at a time. I have extensively researched various guides on migrating between these technologies, completed the A ...

"Prisma vs. Supabase: A Comparison of Image Uploading

I am encountering an issue with adding image URLs to the Prisma database. I have successfully uploaded multiple images from an input file to Supabase storage, but when I try to add their URLs to the database, I receive an error regarding property compatibi ...

Specify the object key type when using a `for-in` loop

My current situation involves an object type: interface ShortUrlParam { openid: string; avatar: string; nickname: string; } const param: ShortUrlParam = { openid: 'abc123', avatar: '', nickname: 'wenzi&apo ...

When trying to install my npm package from the registry, I keep encountering an issue despite being able to install it locally

I recently released my Node.js/typescript package on the npm registry, but I'm encountering issues when trying to install it from there. Oddly enough, local installation works perfectly fine. Here's the output from the local installation: $ npm ...

Conditional return type mistakes

I'm facing an issue with a function that takes a parameter "value" and is supposed to return 0 or 1 based on its true or false value. Check it out here. const f = <T extends boolean>(value: T): false extends T ? 0 : 1 => { if (value === ...

Emphasize the search term "angular 2"

A messenger showcases the search results according to the input provided by the user. The objective is to emphasize the searched term while displaying the outcome. The code snippets below illustrate the HTML and component utilized for this purpose. Compon ...

Dealing with useEffect being invoked twice within strictMode for processes that should only execute once

React's useEffect function is being called twice in strict mode, causing issues that need to be addressed. Specifically, how can we ensure that certain effects are only run once? This dilemma has arisen in a next.js environment, where it is essential ...