Sequelize6.17调用getTempContributions报非函数错误排查
Sequelize 6 懒加载方法报
getTempContributions is not a function修复方案 核心报错原因
Sequelize没有成功在UserCard模型原型上注入关联对应的懒加载实例方法,由三个代码问题共同导致:
- 存在循环模块依赖:
Authority/model.ts顶部导入Temp/model.ts的TempTask,Temp/model.ts顶部又反向导入Authority/model.ts的UserCard。Node/TS处理循环依赖时,会给未完成初始化的模块返回临时导出对象,此时执行UserCard.hasMany(TempContribution)拿到的UserCard不是完成init的有效模型类,关联注册直接失效,自然不会生成对应getter方法。 - 手动类型声明误导:在
UserCard类内部手动声明getTempContributions的TS类型,仅在编译阶段做类型校验,不会在运行时注入真实方法,反而掩盖了关联未注册的TS报错。另外声明的返回值Promise<TempTask[]>和实际关联逻辑不符:UserCard直接关联的是TempContribution,不是TempTask。 - 关联定义前滥用
@ts-ignore:跳过了TS对关联参数合法性的校验,进一步掩盖了循环依赖导致的模型类无效问题。
修复步骤
打破循环依赖(核心修复)
不要在两个模型文件顶部互相导入模型,二选一即可:- 方案1(推荐):抽离统一关联注册文件
删掉两个模型文件顶部互相导入的对方模型代码:Authority/model.ts移除import {TempTask} from "../Temp/model",Temp/model.ts移除import {UserCard} from "../Authority/model"。
新建src/associate.ts,等所有模型完成初始化导出后再注册关联:
在项目入口文件顶部先导入所有模型,再导入该关联文件,保证关联执行时所有模型均已完成初始化。import {UserCard} from "./Authority/model"; import {TempTask, TempContribution} from "./Temp/model"; TempTask.hasMany(TempContribution); TempContribution.belongsTo(TempTask); UserCard.hasMany(TempContribution); TempContribution.belongsTo(UserCard); - 方案2:通过sequelize实例的models集合获取关联模型
不直接跨文件import模型类,关联定义时从已初始化的sequelize实例上取模型,避免循环引用,注意要确保所有模型都调用过init后再执行关联逻辑:// Temp/model.ts 内关联部分示例 const { UserCard } = sequelize.models; TempTask.hasMany(TempContribution); TempContribution.belongsTo(TempTask); UserCard.hasMany(TempContribution); TempContribution.belongsTo(UserCard);
- 方案1(推荐):抽离统一关联注册文件
修正类型声明
删掉UserCard类里手动写的declare getTempContributions,Sequelize 6会自动根据关联推导实例方法的TS类型,手动硬写会覆盖自动推导结果引发类型错误。如果确实需要手动声明,注意返回值应为Promise<TempContribution[]>。如果需要直接获取关联的TempTask列表,可以配置UserCard.belongsToMany(TempTask, { through: TempContribution })多对多关联,会自动生成getTempTasks方法;也可以在调用现有getter时传入include参数嵌套查询。移除无用的
@ts-ignore
循环依赖修复后,关联定义不会再报类型错误,不需要跳过TS校验,后续关联写法有问题时TS可以第一时间提示。
修复后验证代码
import {TempContribution, TempTask} from "./model"; import {UserCard} from "../Authority/model"; // 若用抽离关联文件的方案,记得导入保证关联逻辑执行 import "../associate"; (async ()=>{ const user = await UserCard.findByPk(1); if(user){ // 直接调用返回关联的TempContribution数组 const contributions = await user.getTempContributions(); // 需要关联查询TempTask时传include参数 // const contributions = await user.getTempContributions({ include: [TempTask] }); console.log(contributions); } })()
内容的提问来源于stack exchange,提问作者moneymouse
相关产品推荐
相关产品推荐

