TypeScript下基于Sequelize实现Repository模式的类型适配问题
Sequelize TypeScript Repository层类型适配解决方案
核心问题是泛型与ModelCtor未绑定,导致实例类型与模型静态方法类型不匹配,正确实现如下:
BaseRepository实现
import { Model, ModelCtor } from 'sequelize-typescript'; // 泛型M约束为Model子类,对应具体的模型实例类型 export default abstract class BaseRepository<M extends Model> { // 用ModelCtor<M>声明model类型,绑定静态方法与返回的实例类型M protected model: ModelCtor<M>; constructor(model: ModelCtor<M>) { this.model = model; } // attributes参数做了类型限制,只能传入当前模型存在的字段 public async all(attributes?: Array<keyof M['_attributes']>): Promise<M[]> { return this.model.findAll({ attributes }); } // 其他通用方法示例 public async findById(id: number): Promise<M | null> { return this.model.findByPk(id); } public async create(data: M['_creationAttributes']): Promise<M> { return this.model.create(data); } }
业务Repository实现(以UserRepository为例)
import BaseRepository from './BaseRepository'; import { User } from '../Models'; // 传入User作为泛型参数,绑定具体实例类型 export default class UserRepository extends BaseRepository<User> { constructor() { super(User); } public async findByEmail(email: string): Promise<User | null> { return this.model.findOne({ where: { email } }); } }
方案说明
该实现可以解决所有遇到的类型问题:
this.model的所有Sequelize静态方法(findAll、create、findOne等)都有正确的类型提示,不会报方法不存在的错误- 方法返回的实例都是具体的业务模型类型(如User),可以直接识别自定义属性,访问
user.email不会报类型错误 - 没有类型不匹配的编译报错,不需要加
// @ts-ignore忽略 - 额外优化了入参的类型校验,比如create方法的入参、all方法的attributes参数都会限制为当前模型对应的合法值
- 所有方法都用到了
this.model,不会触发ESLint的类方法必须用this的校验规则
注意:业务模型需要用sequelize-typescript的装饰器正确定义,所有字段都要加@Column装饰器并声明TS类型,才能保证类型推断正常生效。
内容的提问来源于stack exchange,提问作者Deeh
相关产品推荐
相关产品推荐

