嵌套类验证器minDate抛出错误,即使日期更大



我正在使用带有类验证器的Nest,并试图验证UI提供的日期不早于今天使用@isDateString()@MinDate()

export class SchemaDto {
@IsOptional()
@IsDateString()
@MinDate(new Date())
myDate?: Date;
}

我发送进来的数据是一个带有以下日期的Date对象:

Mon Oct 04 2021 00:00:00 GMT-0400 (Eastern Daylight Time)

我从类验证器得到的错误是:

minimal allowed date for myDate is Fri Oct 01 2021 15:57:18 GMT-0400 (Eastern Daylight Time) 

问题:

如果我删除minDate装饰器,一切都可以正常工作,但我宁愿验证这个常见的情况。

信息:打印稿:~ 4.1.4

节点:12.4.0

class-validator: 0.13.1

巢:7.0.0

验证与@MinDate

export class SchemaDto {
@IsNotEmpty()
@Transform( ({ value }) => new Date(value))
@IsDate()
@MinDate(new Date())
myDate: Date;
}

但是如果value是可选的,它可能是null或undefined,所以:

export class SchemaDto {
@IsOptional()
@Transform( ({ value }) => value && new Date(value))
@IsDate()
@MinDate(new Date())
myDate?: Date;
}

海安回答中的@Transform方法有效,因为它省略了OP问题中包含的@IsDateString装饰器。如果您打算保留@IsDateString装饰器,那么当您将其与@Transform装饰器(@Transform( ({ value }) => new Date(value)))一起使用时,您将遇到新的错误。

使用@IsDateString意味着您希望使用ISO8601格式的日期字符串作为输入。问题是@MinDate接受Date类型的参数,而在您的情况下,在运行时传递给它的是字符串。查看MinDate的验证器实现可以发现,如果装饰属性的值不是Date的实例,验证将失败。使用@Transform装饰器将日期字符串转换为日期对象仍然是@IsDateString的一个问题,因为您会得到一个错误,即接收到的输入不是有效的ISO8601日期字符串。这是因为转换发生在应用装饰器之前。好消息是,在GitHub的typestack/class-validator repo中,有一个带有PR的问题,可以修复同时使用@IsDateString@MinDate验证器所带来的冲突——但它看起来不会很快被合并。

解决方案吗?我建议您实现一个自定义装饰器。您可以将装饰器的名称保留为MinDate,这样,当合并/发布指定动态日期PR的功能:Make MinDate和maxDate支持时,您只需要更新类验证器版本并更改MinDate导入路径。下面是我的实现使一行改变最初的实现允许MinDate收到一个日期字符串:

custom-min-date.decorator.ts

import { buildMessage, ValidateBy, ValidationOptions } from 'class-validator';
export const MIN_DATE = 'minDate';
/**
* Checks if the value is a date that's after the specified date.
*/
export function minDate(date: unknown, minDate: Date): boolean {
const dateObject: Date = typeof date === 'string' ? new Date(date) : <Date>date;
return dateObject instanceof Date && dateObject.getTime() >= minDate.getTime();
}
/**
* Checks if the value is a date that's after the specified date.
*/
export function MinDate(date: Date, validationOptions?: ValidationOptions): PropertyDecorator {
return ValidateBy(
{
name: MIN_DATE,
constraints: [date],
validator: {
validate: (value, args): boolean => minDate(value, args.constraints[0]),
defaultMessage: buildMessage(
(eachPrefix) => 'minimal allowed date for ' + eachPrefix + '$property is $constraint1',
validationOptions,
),
},
},
validationOptions,
);
}

我希望这能帮助到别人。

你可以用IsDateString()代替你的IsDate(),它会为你做转换

最新更新