Unable to use cutom validator, since it is saying it is not a function
Hello, I defined a custom validator, as many others i have working correctly, but i am getting an error:
(0, is_valid_order_generation_flow_1.IsValidOrderGenerationFlow)(),
^
TypeError: (0 , is_valid_order_generation_flow_1.IsValidOrderGenerationFlow) is not a function
at Object.
I am using the validator in my express api, which imports it from an npm package i published where i expose types and validators to share between my frontend and backend. Here is how the validator looks in the shared types library:
`import { ValidationArguments, ValidationOptions, ValidatorConstraint, ValidatorConstraintInterface, registerDecorator } from "class-validator"; import { allowedOrderGenerationFlows } from "../../order";
@ValidatorConstraint({ name: 'isValidOrderGenerationFlow', async: false }) class IsValidOrderGenerationFlowConstraint implements ValidatorConstraintInterface { validate(value: any, args?: ValidationArguments | undefined) { return allowedOrderGenerationFlows.includes(value); }
defaultMessage?(validationArguments?: ValidationArguments | undefined): string {
return `Flow de generacion de orden: ${validationArguments?.value} es invalido. Valores posibles son ${allowedOrderGenerationFlows.join(', ')}`;
}
}
export function IsValidOrderGenerationFlow(validationOptions?: ValidationOptions) { return function(object: Object, propertyName: string) { registerDecorator({ target: object.constructor, propertyName, constraints: [], options: validationOptions, validator: IsValidOrderGenerationFlowConstraint, }); } }`
Here is the DTO in the shared library that uses it:
`import { ArrayNotEmpty, IsEmail, IsOptional, IsString } from "class-validator"; import { OrderGenerationFlow } from "."; import { IsValidOrderGenerationFlow } from "../typeorm/custom-validators/is-valid-order-generation-flow";
export class CreateOrderRequestDTO { @ArrayNotEmpty({ message: 'No puede ser un array vacio' }) @IsString({ message: 'Cada elemento debe ser un string', each: true }) items!: string[];
@IsValidOrderGenerationFlow()
orderGenerationFlow!: OrderGenerationFlow;
@IsOptional()
@IsEmail(undefined, { message: "Debe ser un email valido" })
clientEmail?: string;
}`
And here is how i am using it in my backend, just like all other DTOs i use which don't fail, even those using a custom validator:
const requestDTO = await validateRequestBody(OrderDTO.CreateOrderRequestDTO, req.body);
I have another custom validator which doesn't fail which is almost identical to this one, in terms of the validation it performs and the usage inside a DTO. This doesn't fail:
`import { ValidationArguments, ValidationOptions, ValidatorConstraint, ValidatorConstraintInterface, registerDecorator } from "class-validator"; import { allowedProductConditions } from "../../product";
@ValidatorConstraint({ name: 'isValidProductCondition', async: false }) class IsValidProductConditionConstraint implements ValidatorConstraintInterface { validate(condition: any, args: ValidationArguments) { return allowedProductConditions.includes(condition); }
defaultMessage?(validationArguments?: ValidationArguments | undefined): string {
return `Invalid product condition. Allowed product conditions: ${allowedProductConditions.join(', ')}`;
}
}
export function IsValidProductCondition(validationOptions?: ValidationOptions) { return function (object: Object, propertyName: string) { registerDecorator({ target: object.constructor, propertyName, options: validationOptions, constraints: [], validator: IsValidProductConditionConstraint, }); } }`
DTO usage:
` import { Type } from 'class-transformer'; import { ArrayNotEmpty, IsArray, IsBoolean, IsNotEmptyObject, IsNumber, IsOptional, IsPositive, IsString, MinLength, ValidateNested } from 'class-validator'; import { AssignSizeToProductDTO, BaseProductConditionDTO, ProductCondition, ProductSizeDTO } from '.'; import { BaseStoreDTO } from '../store'; import { IsValidProductCondition } from '../typeorm/custom-validators/is-valid-product-condition'; import { ProductBaseCategoryDTO } from './ProductCategory';
export class CreateProductDTO { @IsString() title!: string;
@IsPositive()
price!: number;
@IsValidProductCondition()
condition!: ProductCondition;
@IsNotEmptyObject(undefined, { message: '\'size\' tiene que ser un objeto' })
@ValidateNested()
@Type(() => AssignSizeToProductDTO)
size!: AssignSizeToProductDTO
@IsNumber()
categoryId!: number;
@IsOptional()
@IsString()
description?: string;
@IsOptional()
@IsString()
brand?: string;
@IsOptional()
@IsString()
color?: string;
}`
Please this is driving me nuts, any help is appreciated!
我也遇到了这个问题,在0.14.1新版本也依旧存在。
This isn't a package problem, you have a circular dependency somewhere that prevents the validator from being registered before it is used.
But you see that the type of constraintClass is Function, which is incorrect because the custom validator is an instance of a certain interface, not a function.
https://github.com/typestack/class-validator/blob/develop/src/decorator/common/Validate.ts
Here you can see that CustomTextLength is a class rather than a Function type.