Typegoose如何将泛型类或模型作为函数参数传入?
问题分析与解决方案
问题场景
用户基于Typegoose定义了两个Schema类(User和Ticket),尝试编写泛型函数统一处理数据时触发了多个TypeScript类型错误。
原始Schema代码
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; // 仅作演示 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; // 仅作演示 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; } // 演示调用 let dataToUpdateForUser = genericFunction<User>({firstName: "updatedName"}, User); let dataToUpdateForTicket = genericFunction<Ticket>({message: "updatedMessage"}, Ticket);
触发的TypeScript错误:
- 类型“T”上不存在属性“method1”
- 类型“Partial
”上不存在属性“lastUpdate” - 参数类型“typeof User”无法赋值给类型“User”,缺少必需属性“email”
解决方案
核心问题梳理
你传入的User/Ticket是类本身(构造函数类型),而非类的实例;同时泛型未添加约束,导致TypeScript无法识别类的静态方法和实例属性。
修改后的完整代码
// 定义静态方法的约束类型 type HasStaticMethod1 = { method1?: () => boolean; }; // 定义实例可能存在lastUpdate的约束类型 type HasLastUpdate = { lastUpdate?: Date; }; const genericFunction = <T extends HasLastUpdate, C extends HasStaticMethod1 & (new () => T)>( updDocData: Partial<T>, dataClass: C ): Partial<T> => { // 判断类是否有静态method1且返回true if (dataClass.method1 && typeof dataClass.method1 === 'function' && dataClass.method1()) { // 类型断言确保updDocData可赋值lastUpdate (updDocData as HasLastUpdate).lastUpdate = new Date(); } return updDocData; } // 演示调用(无需手动指定泛型,TypeScript自动推断) let dataToUpdateForUser = genericFunction({firstName: "updatedName"}, User); let dataToUpdateForTicket = genericFunction({message: "updatedMessage"}, Ticket);
关键修正说明
- 泛型参数调整:
C extends HasStaticMethod1 & (new () => T):约束C是能创建T类型实例的构造函数,且可能包含静态方法method1T extends HasLastUpdate:约束T类型的实例可能拥有lastUpdate属性
- 逻辑区分:静态方法
method1属于类本身,判断时直接针对dataClass;lastUpdate是实例属性,通过类型断言处理赋值时的类型检查 - 简化调用:无需手动指定泛型,TypeScript会自动推断
T和C的类型
内容的提问来源于stack exchange,提问作者crivella
相关产品推荐
相关产品推荐

