@ValidateIf
and Inside It Handle the LogicInstead of layering multiple @ValidateIf
s and validators, consolidate validation using a single custom @ValidateIf()
for each conditional branch.
@ValidateIf((o) => o.transactionType === TransactionType.PAYMENT)
@IsNotEmpty({ message: 'Received amount is required for PAYMENT transactions' })
@IsNumber()
receivedAmount?: number;
@ValidateIf((o) => o.transactionType === TransactionType.SALE && o.receivedAmount !== undefined)
@IsEmpty({ message: 'Received amount should not be provided for SALE transactions' })
receivedAmount?: number;
Create a custom validator for receivedAmount
:
import {
registerDecorator,
ValidationOptions,
ValidationArguments,
} from 'class-validator';
export function IsValidReceivedAmount(validationOptions?: ValidationOptions) {
return function (object: any, propertyName: string) {
registerDecorator({
name: 'isValidReceivedAmount',
target: object.constructor,
propertyName: propertyName,
options: validationOptions,
validator: {
validate(value: any, args: ValidationArguments) {
const obj = args.object as any;
if (obj.transactionType === 'PAYMENT') {
return typeof value === 'number' && value !== null;
} else if (obj.transactionType === 'SALE') {
return value === undefined || value === null;
}
return true;
},
defaultMessage(args: ValidationArguments) {
const obj = args.object as any;
if (obj.transactionType === 'SALE') {
return 'receivedAmount should not be provided for SALE transactions';
}
if (obj.transactionType === 'PAYMENT') {
return 'receivedAmount is required for PAYMENT transactions';
}
return 'Invalid value for receivedAmount';
},
},
});
};
}