我试图创建一个通用的prisma数据库模型的 Package 器。这个模型只是一个类型化的对象,表示返回的数据库表行。你可以这样想:
type User = {
user_id: bigint;
password: string;
email_address: string;
}
Package 器围绕这些模型提供了一系列实用程序函数,如下所示:从“lodash”导入;
export default class Entity<T extends {}> {
private readonly cleanModel: T;
private model: Partial<T>| T;
constructor(
model: T,
guardedProps: string[],
) {
this.cleanModel = model;
// By default, hide guarded props. Guarded props are only accessible
// through methods which acknowledge guarded status
const withoutSensitive: Partial<T> = _.omit(model, guardedProps);
this.model = withoutSensitive;
}
/**
* Returns the value of the provided key from the model.
* @param key
*/
prop(key: keyof T): any {
if (key in this.model) {
return this.model[key];
}
throw TypeError(`Key ${String(key)} does not exist on entity Model`);
}
guardedProp(key: keyof T): any {
if (key in this.cleanModel) {
return this.cleanModel[key];
}
throw TypeError(`Key ${String(key)} does not exist on entity Model`);
}
/**
* Picks just the requested keys and returns a new object with those keys.
* To grab guarded properties, the boolean withGuarded can be passed in.
* @param props
* @param withGuarded
* @returns
*/
pick(props: (keyof T)[], withGuarded: boolean = false): Partial<T> {
let picked: Partial<T> = _.pick(withGuarded ? this.cleanModel : this.model, props);
return picked;
}
toString(): string {
return this.model.toString();
}
toJSON(): Partial<T> | T {
return this.model;
}
}
注意model和guardedProps都是Partial类型。我更愿意做的是,让model和guardedProps都是Omit类型,这样我就不必处理Partial的可选性。这将改进IDE完成,并有助于使其不会在日志或API响应中意外泄露敏感信息(如用户密码)。
然而,我似乎找不到一种方法来通用地为实体提供键联合。我愿意为每个模型的每个联合定义类型,但我也找不到一种方法来通用 that。
有没有什么方法可以在类上定义一个属性,该属性的类型为键的联合,并将被接受为Omit中的参数,如Omit<T, T["protectedProps"]
?我已经尝试了protectedProps: (keyof User)[] = ['password', 'user_id']
,它解析得很好,但在实体中导致错误,因为当我尝试前面提到的Omit语法时,keyof T[]
无法分配给keyof T
类型。
2条答案
按热度按时间dgjrabp21#
我想你在找这个。
_Pick
和_Omit
类型,我没有费心去弄清楚它们之间的区别,但是它们似乎与标准的实用程序类型不兼容,所以你不得不使用它们。我注意到
pick
的一个返回类型中包含Partial
,我想您可以安全地关闭它,因为Entity
的构造是穷举的。pod7payv2#
在看到geoffrey的答案后,我花了几个小时来研究这个问题,虽然在类中添加省略的键对输入有用,但它只得到了我需要的类型,在运行或编译时没有足够的信息来帮助我缩小类型范围。
理想情况下,我也不想每次需要一个实体示例时都传入大量类型。所以,如果有人想自己做类似的事情,我最终得到了以下结果。
用户模型
Model类(替换Entity),作为要扩展的基类。
为了使用它,定义了一个表示基本模型的新类,如下图所示。我还定义了表示受保护模型的类型,并且只定义了受保护的属性。
现在我可以简单地将
new UserModel(returnedModelFromPrisma)
类化。