Express+TypeScript+Objection 泛型传Model给父类失效问题
问题根源
类型定义错位导致两个连锁问题:
- 初始代码里BaseService的构造函数参数、
m属性都标注为泛型Models对应的实例类型,当你直接传入UserModel类本身时,TS检测到类型不匹配,才会提示需要加new关键字生成实例 - 按提示传入
new UserModel()实例后,类型报错消失,但Objection.js的query()、findById()等查询方法都是静态方法,挂载在模型类上,模型实例上不存在这些方法,自然无法正常执行查询。
正确实现代码
Objection.js官方自带ModelClass工具类型,专门用来标记模型类本身(而非实例)的类型,直接用就能解决类型匹配问题:
import { Model, ModelClass } from 'objection'; class BaseService<M extends Model> { public model: ModelClass<M>; constructor(model: ModelClass<M>) { this.model = model; } // 可直接在基类封装通用CRUD方法,所有子类自动复用 async getById(id: number | string) { return this.model.query().findById(id); } } class MyService extends BaseService<UserModel> { constructor() { // 直接传入模型类即可,无类型报错 super(UserModel); } async queryUser() { // 两种调用方式都能正常运行,带完整类型提示 const user1 = await this.model.query().findById(1); const user2 = await this.getById(1); return user1; } }
注意事项
- 禁止传入模型实例:所有knex/Objection的查询入口都是模型类的静态方法,实例不携带这些静态方法,传入实例必然导致查询逻辑失效
- 泛型约束
M extends Model会自动校验传入的模型是否符合Objection的Model规范,同时给查询结果提供完整的类型推导 - 不需要自己手写构造函数类型,直接用官方提供的
ModelClass即可,避免手动写类型遗漏静态方法的定义
内容的提问来源于stack exchange,提问作者mayur badodiya
相关产品推荐
相关产品推荐

