假设我定义了这两个模式:
import { prop, getModelForClass, type Ref, ReturnModelType } from '@typegoose/typegoose';
class User {
@prop({ required: true, trim: true })
public email!: string;
@prop({ trim: true })
public firstName?: string;
@prop({ trim: true })
public lastName?: string;
@prop()
public lastUpdate?: Date;
// just for demo
public static method1() {
return true;
}
}
export const UserModel = getModelForClass(User);
class Ticket {
@prop({ required: true, ref: () => User })
public user!: Ref<User>;
@prop()
public dateOpen?: Date;
@prop({ trim: true })
public message?: string;
@prop()
public lastUpdate?: Date;
// just for demo
public static method1() {
return false;
}
}
export const TicketModel = getModelForClass(Ticket);
我需要编写一个接受模型和类作为参数的通用函数,并操作一些数据。像这样的东西:
const genericFunction = <T>(updDocData: Partial<T>, dataClass: T): Partial<T> => {
if (dataClass.method1 && typeof dataClass.method1 === 'function' && dataClass.method1() && dataClass.lastUpdate) {
updDocData.lastUpdate = new Date();
}
return updDocData;
}
// demo use
let dataToUpdateForUser = genericFunction<User>({firstName: "updatedName"}, User);
let dataToUpdateForTicket = genericFunction<Ticket>({message: "updatedMessage"}, Ticket);
我收到大量打字稿错误:
我不知道如何将“User”或“Ticket”类(不是实例)传递给我的通用函数。我无法提前知道 lastUpdate 属性是否存在,也无法知道 method1 。这是我必须在函数内部执行的检查。
我尝试过一些类型,如 ReturnModelType 或 DocumentType,但没有成功。 我错过了什么?
类型“T”上不存在属性“method1”
类型“Partial”上不存在属性“lastUpdate”
您必须限制
T
才能拥有这些属性,例如使用自定义界面(请参见下面的示例)。
“typeof User”类型的参数不可分配给“User”类型的参数。 “typeof User”类型中缺少属性“email”,但“User”类型中需要属性“email”。
Typescript 这里不直观,类的 type(在本例中为
User
)是 实例类型,而不是 static 类型,所以如果你这样做 const t: User = User
,你会得到一个编译错误,但是const t: User = new User()
会起作用的。
有关更多信息,请阅读 typegoose 文档 值和类型之间的区别。
我不完全确定你想用你的函数完成什么,因为它有一个逻辑问题:
您想要接收 typegoose class 并执行 static 方法(
method1
),然后检查 相同值上的 实例属性(
lastUpdate
),但它不是实例。此外,您可能实际上不想在类上调用它,而是在模型上调用它(在本例中 UserModel
)。
由于这个问题,我尽力想出了一个更有可能的情况,如果以下代码不是您搜索的内容,请澄清您想要什么输入以及那里有哪些属性可用。
无论如何,这是代码:
// NodeJS: 22.2.0
// MongoDB: 5.0 (Docker)
// Typescript 5.3.3
import { DocumentType, Ref, getModelForClass, prop } from '@typegoose/typegoose'; // @typegoose/[email protected]
import * as mongoose from 'mongoose'; // [email protected]
interface Updateable {
method1(): boolean;
lastUpdate?: Date;
}
class User {
@prop({ required: true, trim: true })
public email!: string;
@prop({ trim: true })
public firstName?: string;
@prop({ trim: true })
public lastName?: string;
@prop()
public lastUpdate?: Date;
public method1() {
return true;
}
}
export const UserModel = getModelForClass(User);
class Ticket {
@prop({ required: true, ref: () => User })
public user!: Ref<User>;
@prop()
public dateOpen?: Date;
@prop({ trim: true })
public message?: string;
@prop()
public lastUpdate?: Date;
public method1() {
return false;
}
}
export const TicketModel = getModelForClass(Ticket);
interface MaybeLastUpdate {
lastUpdate?: Updateable['lastUpdate'];
}
function genericFunction<T extends MaybeLastUpdate, D extends mongoose.Document & Updateable>(
updDocData: T,
dataDoc: D
): T & MaybeLastUpdate {
if (dataDoc.method1 && typeof dataDoc.method1 === 'function' && dataDoc.method1() && dataDoc.lastUpdate) {
updDocData.lastUpdate = new Date();
}
return updDocData;
}
const userDoc = new UserModel();
const ticketDoc = new TicketModel();
const dataToUpdateForUser = genericFunction<Partial<User>, DocumentType<User>>({ firstName: 'updatedName' }, userDoc);
const dataToUpdateForTicket = genericFunction<Partial<Ticket>, DocumentType<Ticket>>({ message: 'updatedMessage' }, ticketDoc);
console.log('dataToUpdateForUser', dataToUpdateForUser);
console.log('dataToUpdateForTicket', dataToUpdateForTicket);
(此代码也可以在 typegoose-testing 分支中找到)
注意:根据函数实际需要的内容,此代码可能会被更多地清理