TypeScript:使用自定义验证值扩展密钥



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

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'> {
}

但我想得到一个更可重用的解决方案。有人试图制作类似的东西吗?

您可以将 Record 类型与 keyof 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 时,这才重要。

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

这是枚举的另一种解决方案。

最新更新