【发布时间】:2022-11-22 05:14:45
【问题描述】:
我正在尝试围绕 prisma 数据库模型创建通用包装器。该模型只是一个类型化对象,表示要返回的数据库表行。你可以这样想:
type User = {
user_id: bigint;
password: string;
email_address: string;
}
包装器围绕这些模型提供了一堆实用函数,看起来像这样:
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 响应中意外泄露。
但是,我似乎无法找到一种方法来为 Entity 提供通用的键联合。我愿意为每个模型的每个联合定义类型,但我找不到通用化的方法那任何一个。
有什么方法可以在类上定义一个属性,该属性被键入为键的联合,并且可以像 Omit<T, T["protectedProps"] 一样被接受为 Omit 中的参数?我试过 protectedProps: (keyof User)[] = ['password', 'user_id'] 解决得很好,但在实体中导致错误,因为当我尝试前面提到的 Omit 语法时,keyof T[] 不可分配给类型 keyof T。
【问题讨论】:
标签: typescript generics prisma