Confirm that the array includes all unique objects that have the specified properties and values

I have been searching through the class-validators samples and documentation, but I have not been able to find the specific validation that I require.

Within my code, I have an array of object literals that each contain unique properties and values.

const comboItems = [{itemType: 'Entree'}, {itemType: 'Side'}, {itemType: 'Beverage'}];

My goal is to validate the following criteria for the comboItems array: it must not be empty, it must contain a minimum and maximum of 3 objects, and it must include one object with itemType === 'Entree', another with itemType === 'Side', and a third with itemType === 'Beverage'.

Below is the class I have created, which does not provide the correct validation:

import {validate, ArrayContains, ArrayNotEmpty, ArrayMinSize, ArrayMaxSize} from 'class-validator';
import { plainToClass } from 'class-transformer';

export class MealMenuItem {
    @ArrayContains([{itemType: 'Entree'}, {itemType: 'Side'}, {itemType: 'Beverage'}])
    @ArrayNotEmpty()
    @ArrayMinSize(3)
    @ArrayMaxSize(3)
    comboItems: any[];
}

const mealMenuItemData: any = {comboItems: [{itemType: 'Entree'}, {itemType: 'Side'}, {itemType: 'Beverage'}]};

const mealMenuItemDataClassInstance = plainToClass(MealMenuItem, mealMenuItemData as MealMenuItem)

validate(mealMenuItemDataClassInstance).then(errors => {
    if (errors.length > 0) 
        console.log('validation failed. errors: ', JSON.stringify(errors));
    else 
        console.log('validation succeed');
});

If anyone can offer assistance, I would greatly appreciate it!

Answer №1

The method of the ArrayContains decorator is designed solely to validate primitive types, as indicated by this snippet from the class-validator module:

export function arrayContains(array: unknown, values: any[]): boolean {
  if (!(array instanceof Array)) return false;

  // Returns false for object items
  return values.every(value => array.indexOf(value) !== -1);
}

View source code

To enhance validation for your itemType field, you can create a custom decorator like so:

import {
    validate,
    ArrayMinSize,
    ArrayMaxSize,
    registerDecorator,
    ValidationOptions,
    ValidationArguments
} from 'class-validator';
import { plainToClass } from 'class-transformer';

function ContainSequenceOf(property: string, validationOptions?: ValidationOptions & { containThese: string[] }) {
    return function (object: Object, propertyName: string) {
        registerDecorator({
            name: 'containSequenceOf',
            target: object.constructor,
            propertyName: propertyName,
            constraints: [property],
            options: validationOptions,
            validator: {
                validate(value: any, args: ValidationArguments) {
                    const [relatedPropertyName] = args.constraints;
                    return value.every((item, i) => {
                        return item[relatedPropertyName] === validationOptions?.containThese[i]
                    })
                },
            },
        });
    };
}
export class MealMenuItem {
    @ContainSequenceOf('itemType', {
        message: "Is Not Valid!",
        containThese: ['Entree', 'Side', 'Beverage']
    })
    @ArrayMinSize(3)
    @ArrayMaxSize(3)
    comboItems: any[];
}

const mealMenuItemData: any = {comboItems: [{ itemType: 'Entree' }, { itemType: 'Side' }, { itemType: 'Beverage' }]};
const mealMenuItemDataClassInstance = plainToClass(MealMenuItem, mealMenuItemData as MealMenuItem)

validate(mealMenuItemDataClassInstance).then(errors => {
    if (errors.length > 0) 
        console.log('Validation failed. Errors: ', JSON.stringify(errors));
    else 
        console.log('Validation successful');
});

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

What is the best way to create props that can accommodate three distinct types of functions in TypeScript?

I have been encountering a problem with the last function in my props interface that is supposed to support 3 different types of functions throughout the application. Despite adding parentheses as requested, I am still facing errors. // In Parent compon ...

Enhance the Next.js higher-order authentication component by including extra data in the return

Below is the code snippet I am working with: export const requireAuth = (gssp: GetServerSideProps) => { return async (ctx: GetServerSidePropsContext) => { const { req } = ctx; let session = null; if (req?.headers?.cookie) { sessi ...

In Typescript, what is the antonym of "Choose"?

I'm attempting to create a custom type that can remove specific properties from an object, unlike the Pick utility. The desired functionality is as follows: type ObjectType = { key1: number, key2: string, key3: boolean, key4: num ...

Utilize the expert capabilities within #dateHeaderTemplate in the Angular component schedule by Syncfusion

I am trying to access the template #dateHeaderTemplate in order to retrieve the ID of the professional who is scheduled to attend the appointment. This information is needed to display the start and end times of the day in the header. By visiting this lin ...

What is the best way to change the name of an imported variable currently named `await` to avoid conflicting with other variables?

Here is the given code snippet: import * as fs from 'fs'; import {promises as fsPromises} from 'fs'; // ... // Reading the file without encoding to access raw buffer. const { bytesRead, buffer as fileBuffer } = await fsPromises.read( ...

The initial function is executed only after the second function has completed, as it relies on the

For a small project of mine, I've been attempting to load JSON data. However, the issue arises when the loadDefs function is executed before checking if file_data has been modified. loadDefs(file_path:any) { let file_data:string = '&a ...

Caution: Ensuring that every child item in a list possesses a distinct "key" prop is crucial when working with React in TypeScript

Encountering this issue in React (TypeScript): Notification: Each child in a list requires a unique "key" prop. Review the render method of MyCollection Below is the implementation of MyCollection: export default function MyCollection(props:any ) { le ...

A guide on utilizing portals in Next.js to move a child element beyond its direct parent container

Current Setup Wrapper export const ContainerComponent = () => { return (<ChildComponent/>); } Child Component export const ChildComponent = () => { return ReactDOM.createPortal( <aside> <div>{"I am a c ...

In TypeScript, combining the numbers 0 and 1 results in the value 01

I am in the process of developing a Shopping Card feature. private _card: Map<Product, number> = new Map<Product, number>(); ... addToCard(prod: Product, amount: number = 1): void { const totalAmount: number = this._card.get(prod) + amou ...

Using arrow functions in Typescript e6 allows for the utilization of Array.groupBy

I'm attempting to transform a method into a generic method for use with arrow functions in JavaScript, but I'm struggling to determine the correct way to do so. groupBy: <Map>(predicate: (item: T) => Map[]) => Map[]; Array.prototype ...

Creating a Loading Sign with a Button Component in React

Request Description: In my form, I have a button that triggers a submission to the backend. While the request is processing, I want the button to display a loading indicator instead of the usual text. Once the request is complete, I need the form to disap ...

What is the best way to automatically refresh an observable every 30 seconds?

@Component({ selector: 'app-geo', templateUrl: <img mat-card-image [src]="profileUrl | async "> export class GeoComponent implements OnInit { date; profileUrl: Observable<string>; constructor(private tempService ...

How can I confine a non-UMD module that has been imported in Webpack and Typescript to just one file?

When working on a project that involves Typescript and Webpack, I want to make sure that global libraries, such as jQuery, are treated as UMD globals. Currently, if I do not include import * as $ from 'jQuery' in a file where I am using $, webpa ...

Is it possible to retrieve 2 arguments within a function in a non-sequential manner?

Let's say there is a function with arguments A, B, C, D, and E. Function(A, B, C, D, E) However, not all arguments are needed all the time. For instance, only A and C are needed in some cases. Currently, I would have to call the function like this: Fu ...

How to create a boolean observable that emits hot values with switchMap?

Looking to develop a method named isEmpty:Observable<boolean> that generates a hot Observable<boolean> by employing a switchMap. Here's what I have so far: /** * Notifies observers when the store is empty. */ protected notifyOnE ...

Creating an interface or type in Typescript with a nested object property that uses keys from the same interface

I am looking to create an interface or type that can restrict the nested object properties based on keys defined in the main interface. class MyClass implements MyInterface { prop1: string; promp2: number; nestedObj: { prop1: string; // Allowed a ...

Nextjs 14 experiences full page loading due to the presence of multiple root layouts

The issue I'm facing involves a full page load when navigating between two root layout pages In my Next.js application (NextJS 14), I have created two root layouts. However, when moving from the first layout to the second layout, it triggers a comple ...

Capturing a webpage through Record RTC integration with Angular

I am looking to record a specific section of the page as a video with audio. For example, when a user enters the page, I want it to automatically start recording the activities in that particular area (similar to how iframe videos work). The recording sh ...

Angular 6: Sending Back HTTP Headers

I have been working on a small Angular Application for educational purposes, where I am utilizing a .net core WebApi to interact with data. One question that has come up involves the consistent use of headers in all Post and Put requests: const headers = ...

TS - deduce the specific type of a key value without receiving a union type

Welcome to the coding playground: Click here to start coding Let's talk about a scenario where a function is expected to return some value based on an input argument. The challenge arises when there are keys with the same name but different types re ...