gpt4 book ai didi

typescript - 如何在 Typescript 中轻松重用一组装饰器

转载 作者:行者123 更新时间:2023-12-03 16:48:03 25 4
gpt4 key购买 nike

TL; 博士

How to group decorators (from a library) together into 1 re-usable decorator


问题
每次我的 REST API 收到请求时,它都会验证提供的主体属性(使用 class-validator 库)。每个路由都有自己专用的验证类(在代码中它们称为 Dtos)( 参见示例 )
每个提供的 body 属性都有几个验证规则,这些规则有时会变得非常复杂, 其他工程师应该能够轻松地重用这些验证规则 .
例子
路线一:公司创建
POST - /api/company
>> Parameters: name, domain, size, contact
class CreateCompanyDto implements Dto {
@IsString({message: 'Must be text format'})
@MinLength(2, { message: "Must have at least 2 characters" })
@MaxLength(20, { message: "Can't be longer than 20 characters" })
@IsDefined({ message: 'Must specify a receiver' })
public name!: string;

@MaxLength(253, { message: "Can't be longer than 253 characters" })
@IsFQDN({}, {message: 'Must be a valid domain name'})
@IsDefined({ message: 'Must specify a domain' })
public domain!: string;

@MaxLength(30, { message: "Can't be longer than 30 characters" })
@IsString({message: 'Must be text format'})
@IsDefined({ message: 'Must specify a company size' })
public size!: string;

@IsPhoneNumber(null, {message: 'Must be a valid phone number'})
@IsDefined({ message: 'Must specify a phone number' })
public contact!: string;
}
路线2:公司更新
PUT - /api/company
>> Parameters: id, name, domain, size, contact
class UpdateCompanyDto implements Dto {

@IsUUID()
@IsDefined({ message: 'Must be defined' })
public id!: string;

@IsString({ message: 'Must be text format' })
@MinLength(2, { message: "Must have at least 2 characters" })
@MaxLength(20, { message: "Can't be longer than 20 characters" })
@IsOptional()
public name!: string;

@MaxLength(253, { message: "Can't be longer than 253 characters" })
@IsFQDN({}, { message: 'Must be a valid domain name' })
@IsOptional()
public domain!: string;

@MaxLength(30, { message: "Can't be longer than 30 characters" })
@IsString({ message: 'Must be text format' })
@IsOptional()
public size!: string;

@IsPhoneNumber(null, { message: 'Must be a valid phone number' })
@IsOptional()
public contact!: string;
}
我在寻找什么
正如您在示例中看到的那样,一个验证类需要使用另一个验证类的属性的情况并不少见。
问题在于,如果工程师向随机验证类中的属性添加 1 条验证规则,则其他验证类不会动态更新。
问题:确保装饰器一旦更改/添加其他验证类就知道更新的最佳方法是什么。
有没有办法将它们组合成一个变量/装饰器?感谢任何 Typescript 大师的任何帮助!
可接受的结果:
class CreateCompanyDto implements Dto {
@IsCompanyName({required: true})
public name!: string;

@IsCompanyDomain({required: true})
public domain!: string;

@isCompanySize({required: true})
public size!: string;

@isCompanyContact({required: true})
public contact!: string;
}

class UpdateCompanyDto implements Dto {

@IsCompanyId({required: true})
public id!: string;

@IsCompanyName({required: false})
public name!: string;

@IsCompanyDomain({required: false})
public domain!: string;

@isCompanySize({required: false})
public size!: string;

@isCompanyContact({required: false})
public contact!: string;
}

最佳答案

由于装饰器的功能特性,您可以轻松定义自己的装饰器工厂以调用所有必需的验证器:

export function IsCompanyName({ required }: { required: boolean }): PropertyDecorator {
return function (target: any,
propertyKey: string | symbol): void {
IsString({ message: 'Must be text format' })(target, propertyKey);
MinLength(2, { message: "Must have at least 2 characters" })(target, propertyKey);
MaxLength(20, { message: "Can't be longer than 20 characters" })(target, propertyKey);
if (required)
IsDefined({ message: 'Must specify a receiver' })(target, propertyKey);
else
IsOptional()(target, propertyKey);
}
}
Playground
一家小型装饰厂工厂
export function ValidatorComposer(validators: PropertyDecorator[], name: string): (options: { required: boolean }) => PropertyDecorator {
return function ({ required }: { required: boolean }) {
return function (target: any,
propertyKey: string | symbol): void {
validators.forEach((validator) => validator(target, propertyKey));
if (required)
IsDefined({ message: 'Must specify a ' + name })(target, propertyKey);
else
IsOptional()(target, propertyKey);
}
}
}
Playground

关于typescript - 如何在 Typescript 中轻松重用一组装饰器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63836176/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com