【发布时间】:2021-06-01 02:47:08
【问题描述】:
因为它是一种不同类型的“数组验证”,所以我正在努力弄清楚如何做到这一点。
本质上,我想从函数参数中获取动态的剩余参数集,并根据 REST api 的模式验证它们。例如:
@Validation(Schema.update)
public async update(id: string, model: Model) => { }
然后使用我的装饰器拦截函数调用并根据提供的模式进行验证:
export function Validation(schema: ObjectSchema) {
return (target: any, propName: string | symbol, descriptor: PropertyDescriptor): void => {
const originalMethod = descriptor.value!;
descriptor.value = function (...rest: any[]): ApiResult {
const { error } = schema.validate({ ...rest });
if (error) {
console.error(error.message);
return new ErrorApiResult({ statusCode: 400, message: error?.message });
}
return originalMethod.apply(this, arguments);
};
};
}
目前,我想指出,除了我必须像这样创建我的验证架构之外,这非常有效:
export const Schema = {
update: Joi.object({
0: Joi.string(),
1: ModelSchema,
}),
}
这样做的主要问题是验证错误消息 Joi 生成的字段标签为 0.user.name 而不是 model.user.name 等。
我想改写上面的端点架构,如:
export const Schema = {
update: Joi.object({
id: Joi.string().required(),
model: ModelSchema,
}),
}
但我不知道该怎么做。查看 Joi.array(),它似乎只用于处理对象集合,而不是严格的参数数组。
编辑:
我尝试使用.label() 方法更改错误消息中的标签,但如果错误在于嵌套键,则此方法不起作用。例如,如果我的 id 参数没有正确验证,它会起作用,但如果我的 ModelSchema 无法在子属性上验证,它就不会正确显示。它仍然在错误消息中显示为"1.user.name"。
【问题讨论】:
-
这只是完全绕过了数组,但是您是否考虑过在对象中传递所有函数参数?在解构时代,
public async update({ id: string, model: Model })这样的签名并非闻所未闻。这将提供一个已经匹配您想要编写架构的方式的结构。 -
其实我确实考虑过。但是由于 Typescript 的类型安全,如果我想避免使用
any打字,就必须为我的所有 API 方法定义单独的接口似乎很麻烦。
标签: typescript joi