TypesScript:使用自定义验证值扩展键

时间:2019-06-18 11:18:51

标签: javascript typescript generics

我正在尝试扩展类键并设置自定义值以进行验证。

class FindUserDto {

  readonly _id?: string | object;
  readonly email?: string;
  readonly firstName?: string;
  readonly lastName?: string;
}

我需要创建一个SortBy类,该类应从FindUserDto中获取键并将'ASC''DESC'验证为传入值。这样的事情。

class SortBy {
  readonly email: 'ASC' | 'DESC';
  readonly firstName: 'ASC' | 'DESC';
  readonly lastName: 'ASC' | 'DESC';
}

但是我要避免复制和粘贴,这就是为什么我要使用打字稿来解决它。

我试图像这样的[K in keyof FindUserDto][key: K]这样的K extends {[T in keyof FindUserDto]}动态设置键,但是它不起作用。 Typescript不允许实现这种流程。

目前最简单的解决方案是通过在内部传递类型来升级FindUserDto类:

class FindUserDto<T>{
  _id?: T;
  readonly email?: T;
  readonly firstName?: T;
  readonly lastName?: T;
}


class SortBy extends FindUserDto<'ASC' | 'DESC'> {

}

但是我想得到一个更可重用的解决方案。有人尝试做类似的事情吗?

2 个答案:

答案 0 :(得分:0)

您可以将Recordkeyof T结合使用。使用这个SortBy不会是一个类,它将是一个类型别名,您可以使用任何对象文字来实现它:

class FindUserDto {
    readonly _id?: string | object;
    readonly email?: string;
    readonly firstName?: string;
    readonly lastName?: string;
}

type SortBy = Record<keyof FindUserDto, 'ASC' | 'DESC'> 
// type SortBy = Record<Exclude<keyof FindUserDto, "_id">, 'ASC' | 'DESC'> // or remove _id 
let sortBy: SortBy = {
    _id: "ASC",
    email: "DESC",
    firstName: "DESC",
    lastName: "ASC"
}

或者您也可以将其实现为类,但是您将不得不重新声明字段(尽管编译器确保将所有字段都重新声明):

class SortBy implements Record<keyof FindUserDto, 'ASC' | 'DESC' | undefined>  {
    _id: "ASC" | "DESC"| undefined;
    email: "ASC" | "DESC"| undefined;
    firstName: "ASC" | "DESC"| undefined;
    lastName: "ASC" | "DESC"| undefined;
}

如果不重新声明所有字段,则还可以创建一个伪类,假装为实现字段而设计,以利于编译器:

function sortByClass<T>() : new () => Record<keyof T, 'ASC' | 'DESC' | undefined> {
    return class {} as any
}
class SortBy extends sortByClass<FindUserDto>() {
}

注意:由于未初始化字段,因此我在字段类型中添加了| undefined,以使字段类型与实际可能性保持一致。仅在使用stricyNullChecks时才重要。

答案 1 :(得分:0)

class FindUserDto {
  readonly _id?: string | object;
  readonly email?: string;
  readonly firstName?: string;
  readonly lastName?: string;
}

type Sortable <T> = {
   [P in keyof T]: 'ASC' | 'DESC';
};

let a: Sortable<FindUserDto>; 

a = { email: 'ASC', firstName: 'DESC', lastName: 'ASC' };

// a = { email: 'ASC', firstName: 'DESC', lastName: 'ASC123' }; //error

这是另一种解决方案with enums