`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

Creating a functional component in React using TypeScript with an explicit function return type

const App: FC = () => { const addItem = () => { useState([...items, {id:1,name:'something']) } return <div>hello</div> } The linter is showing an error in my App.tsx file. warning There is a missing return type ...

When assigning JSON to a class object, the local functions within the class became damaged

This is a demonstration of Object Oriented Programming in JavaScript where we have a parent Class called Book with a child class named PriceDetails. export class Book { name: String; author: String; series: String; priceDetails: Array<Price> ...

Angular 7 router navigate encountering a matching issue

I created a router module with the following configuration: RouterModule.forRoot([ {path: 'general', component: MapComponent}, {path: 'general/:id', component: MapComponent}, {path: '', component: LoginComponent} ]) Sub ...

Using TypeScript to create a generic type that wraps around HTMLElements

I attempted to execute this action, however the assignment to this.element is not working and I am unsure why. class Elem<T> { public element : T; constructor(typeElement:string){ this.element = document.createElement(typeElement); ...

Exploring the power of Vue.js reactivity using Object.defineProperty in a TypeScript environment

Currently, I am in the process of developing a TypeScript class to manage form submissions and handle server errors: export default class Form<Model> { private readonly original: Model private changes: Partial<Model> constructor(d ...

React TypeScript - Module not found

Organizational structure: src - components - About.tsx In an attempt to optimize performance, I am experimenting with lazy loading: const About = React.lazy(() => import('components/About')); However, Visual Studio Code is flagging &ap ...

Exploring Click Events in Angular with OpenLayers Features

After creating a map with parking points as features, I now want to implement a click function for the features. When a feature is clicked, I want to display a popup with the corresponding parking data. I've tried searching online for information on ...

Tips for Customizing the Width of Your Material UI Alert Bar

At the moment, I have refrained from using any additional styling or .css files on my webpage. The width of the Alert element currently spans across the entire page. Despite my attempts to specify the width in the code snippet below, no noticeable change ...

Discovering the ASP.NET Core HTTP response header in an Angular application using an HTTP interceptor

I attempted to create a straightforward app version check system by sending the current server version to the client in the HTTP header. If there's a newer version available, it should trigger a notification for the user to reload the application. Ini ...

Develop a custom cell editor for ag-Grid and insert it into a designated location within

I am currently working with Angular 16 and AgGrid 30. My goal is to have the cell editor created in a different location than its default position, which is within a div element at the bottom of the body with these classes: ag-theme-material ag-popup. I w ...

There is no overload that matches this call in Next.js/Typescript

I encountered a type error stating that no overload matches this call. Overload 1 of 3, '(props: PolymorphicComponentProps<"web", FastOmit<Omit<AnchorHTMLAttributes, keyof InternalLinkProps> & InternalLinkProps & { ...; ...

The argument with type 'void' cannot be assigned to a parameter with type 'Action'

Just getting started with Typescript and using VSCode. Encountering the following Error: *[ts] Argument of type 'void' is not assignable to parameter of type 'Action'. (parameter) action: void Here is the code snippet causing the err ...

Organizing JSON keys based on their values using Typescript

In the context of a main JSON structure represented below, I am interested in creating two separate JSONs based on the ID and Hobby values. x = [ {id: "1", hobby: "videogames"}, {id: "1", hobby: "chess"}, {id: "2", hobby: "chess ...

Display a child element depending on a certain condition

Looking to implement a switch higher-order component (HOC) for conditional rendering that mimics a switch statement in ReactTS. <Switch> <Case condition={cond1}> Hello </Case> <Case condition={cond2}> Wor ...

Using React with Typescript: Can the parent component access data fetched from a nested child component?

Can I access data retrieved from a child component (using a graphql query) in a parent component? For example, how can I use the data fetched by React-component-4 in React-component-1? Is there a way to do this or do I have to duplicate the data fetching ...

React/TypeScript - react-grid-layout: The onDrag event is fired upon clicking the <div> element

I am currently working on creating a grid with clickable and draggable items using the react-layout-grid component. However, I am facing an issue where the drag is instantly activated when I click on the item without actually moving the cursor. Is there a ...

Exploring the concept of rest arrays within a destructured object

Is there a way to declare c as an optional array of any type in this code snippet? const a = ({ b, ...c }: { b: string, c: ? }) => null ...

Error message in Typescript with React: "The type 'ComponentClass<StyledComponentProps<{}>>' cannot be assigned to type 'typeof MyComponent'"

Currently experimenting with integrating the Material UI 1.0 (beta) @withStyles annotation into a React component. The documentation provides a JavaScript example (), however, it results in a compilation error when using Typescript. Despite the error, the ...

Using Javascript to parse SOAP responses

Currently, I am working on a Meteor application that requires data consumption from both REST and SOAP APIs. The SOAP service is accessed using the soap package, which functions properly. However, I am facing challenges with the format of the returned data ...

Issues encountered when attempting to add a new user on Firebase

I am facing an issue with this function that is supposed to add new users to my firebase database, but for some reason, it's not working. exports.createUserWithEmailAndPassword = functions.https.onCall( async(data, context) => { const { ...