You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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);

关键修正说明

  1. 泛型参数调整:
    • C extends HasStaticMethod1 & (new () => T):约束C是能创建T类型实例的构造函数,且可能包含静态方法method1
    • T extends HasLastUpdate:约束T类型的实例可能拥有lastUpdate属性
  2. 逻辑区分:静态方法method1属于类本身,判断时直接针对dataClass;lastUpdate是实例属性,通过类型断言处理赋值时的类型检查
  3. 简化调用:无需手动指定泛型,TypeScript会自动推断T和C的类型

内容的提问来源于stack exchange,提问作者crivella

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 16:13:10