验证数组包含具有特定属性和值的每个对象之一

时间:2020-11-08 02:41:50

标签: typescript class-validator

我查看了类验证器的示例和文档,但找不到所需的验证。

我有一组对象常量,每个对象都有特定的属性和值。

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

我想验证comboItems是否为空,并且包含3个对象的最小值和最大值,以及是否有itemType ==='主菜'和itemType ==='侧面'和itemType ==='饮料'

这是我创建的未提供正确验证的类:

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');
});

感谢您的帮助!

1 个答案:

答案 0 :(得分:2)

由于ArrayContains模块的这一行,primitive装饰器方法仅验证class-validator类型:

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

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

source code

因此,您可以创建一个自定义装饰器来验证您的itemType字段,如下所示:

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 succeed');
});