为了账号安全,请及时绑定邮箱和手机立即绑定

如何在类型中传递泛型类型?

如何在类型中传递泛型类型?

拉莫斯之舞 2021-11-12 18:36:48
我正在尝试为 Typestack 类验证器创建一个新约束。“IsUnique”约束将实体作为类型,它的列作为参数来检查该列是否在数据库中不存在并且是唯一的。我已经尝试了下面的代码,但不知何故我无法通过 registerDecorator 中的验证器键将类型传递给“IsUniqueConstraint”。因为,我是 Typescript 的新手,所以我不太了解它的概念。有人可以帮我知道我们该怎么做吗?is-unique.constraint.tsimport { registerDecorator, ValidatorConstraint, ValidatorConstraintInterface, ValidationArguments, ValidationOptions } from 'class-validator';import { Injectable } from '@nestjs/common';import { Repository } from 'typeorm';@ValidatorConstraint({ name: 'isUnique', async: true })@Injectable()export class IsUniqueConstraint<T> implements ValidatorConstraintInterface {    constructor(private readonly repository: Repository<T>) { }    async validate(value: string, args: ValidationArguments) {        const [column] = args.constraints;        const result = await this.repository.findOne({ where: { [column]: value } });        if (result) {            return false;        }        return true;    }    defaultMessage(args: ValidationArguments) {        return `"${args.value}" already exists for ${args.constraints[0]}`;    }}export function IsUnique<T>(column: string, validationOptions?: ValidationOptions) {    return (object: object, propertyName: string) => {        registerDecorator({            target: object.constructor,            propertyName,            options: validationOptions,            constraints: [column],            validator: IsUniqueConstraint,        });    };}用户.dto.tsimport { IsNotEmpty } from 'class-validator';import { IsUnique } from './../shared/constraints/is-unique.constraint';import { User } from './user.entity';export class CreateUserDto {  @IsNotEmpty()  @IsUnique<User>('username')  readonly username: string;}
查看完整描述

2 回答

?
MMMHUHU

TA贡献1834条经验 获得超8个赞

泛型通常是仅编译时功能。除非您有某种方式发出元数据,包括泛型(不确定这是否容易实现)。


如果需要在运行时使用类型,通常应该将其作为常规参数传递,因此在这种情况下,必须更改签名以适应这一点:


@IsUnique(User, 'username')

这可能就是为什么在注入存储库时您通过 来执行它@InjectRepository(User),它也将实体类作为参数。我怀疑是否IsUniqueConstraint可以按原样注入存储库。您可能需要根据装饰器传递的实体类型从 DI 容器/连接管理器解析它。


根据文档,您可以直接将对象分配给validator,而不仅仅是类/构造函数,因此您可以创建验证器的具体实例,手动将解析的存储库传递给构造函数。


所以,也许是这样的:


import { getRepository } from "typeorm";

// ...


export function IsUnique(

    entity: Function,

    column: string,

    validationOptions?: ValidationOptions) {


    // Not sure if this works here. Maybe it needs to be

    // moved into the returned function or a different resolution

    // mechanism is required.

    const repository = getRepository(entity); 


    return (object: object, propertyName: string) => {

        registerDecorator({

            target: object.constructor,

            propertyName,

            options: validationOptions,

            constraints: [column],

            validator: new IsUniqueConstraint(repository),

        });

    };

}


查看完整回答
反对 回复 2021-11-12
?
心有法竹

TA贡献1866条经验 获得超5个赞

好的,在尝试了很多之后,我以另一种方式解决了它。感谢@HB 向我展示了路径。


为了做同样的事情,我将实体传递给验证器并在类本身中生成存储库。因为 Nest JS 注入仅适用于类。


import { registerDecorator, ValidatorConstraint, ValidatorConstraintInterface, ValidationArguments, ValidationOptions } from 'class-validator';

import { Injectable } from '@nestjs/common';

import { Connection } from 'typeorm';

import { InjectConnection } from '@nestjs/typeorm';


@ValidatorConstraint({ name: 'isUnique', async: true })

@Injectable()

export class IsUniqueConstraint implements ValidatorConstraintInterface {


    constructor(@InjectConnection() private readonly connection: Connection) { }


    async validate(value: string, args: ValidationArguments) {

        const [entity, column] = args.constraints;


        const repository = this.connection.getRepository(entity);

        const result     = await repository.findOne({ where: { [column]: value } });


        if (result) {

            return false;

        }


        return true;

    }


    defaultMessage(args: ValidationArguments) {

        return `"${args.value}" already exists for ${args.constraints[1]}`;

    }


}


export function IsUnique(entity: Function, column: string, validationOptions?: ValidationOptions) {

    return (object: object, propertyName: string) => {

        registerDecorator({

            target: object.constructor,

            propertyName,

            options: validationOptions,

            constraints: [entity, column],

            validator: IsUniqueConstraint,

        });

    };

}


查看完整回答
反对 回复 2021-11-12
  • 2 回答
  • 0 关注
  • 280 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信