Loopback 4 JWT认证报错:userCredentials不是函数
LoopBack 4 JWT认证注册报错:TypeError: this.userRepository.userCredentials is not a function
问题概述
- 技术栈:TypeScript + LoopBack 4 + @loopback/authentication-jwt
- 操作流程:整合多篇教程开发JWT认证,创建空User模型生成数据表,复制官方示例控制器并修正导入
- 触发场景:调用
/signup接口注册用户时返回500错误 - 具体报错:
错误位置:控制器第156行TypeError: this.userRepository.userCredentials is not a function - 排查信息:UserRepository中
userCredentials为HasOneRepositoryFactory类型(接口定义为可调用函数),但调用仍报错;已关联Github Issue #6964,项目可通过docker compose启动复现
解决方案
1. 检查UserRepository的关联配置
确保UserRepository中正确初始化HasOne关联的仓库工厂:
export class UserRepository extends DefaultCrudRepository< User, typeof User.prototype.id, UserRelations > { public readonly userCredentials: HasOneRepositoryFactory<UserCredentials, typeof User.prototype.id>; constructor( @inject('datasources.db') dataSource: DbDataSource, @repository.getter('UserCredentialsRepository') userCredentialsRepositoryGetter: Getter<UserCredentialsRepository>, ) { super(User, dataSource); // 初始化HasOne关联工厂 this.userCredentials = this.createHasOneRepositoryFactoryFor( 'userCredentials', userCredentialsRepositoryGetter, ); // 注册包含解析器(可选,用于关联查询) this.registerInclusionResolver('userCredentials', this.userCredentials.inclusionResolver); } }
2. 修正控制器中关联仓库的调用方式
HasOneRepositoryFactory是工厂函数,需要传入用户ID来获取对应的UserCredentialsRepository实例,再执行创建操作:
// 错误写法(直接调用工厂函数但未传参) // await this.userRepository.userCredentials({ password: hashedPassword }); // 正确写法 // 1. 先通过用户ID获取关联仓库实例 const userCredentialsRepo = this.userRepository.userCredentials(newUser.id); // 2. 调用关联仓库的create方法创建凭证 await userCredentialsRepo.create({ password: hashedPassword });
3. 验证模型关联配置
确保User和UserCredentials模型的双向关联定义正确:
- User模型:
@model() export class User extends Entity { @property({ type: 'number', id: true, generated: true, }) id?: number; // 定义HasOne关联 @hasOne(() => UserCredentials) userCredentials?: UserCredentials; constructor(data?: Partial<User>) { super(data); } } - UserCredentials模型:
@model() export class UserCredentials extends Entity { @property({ type: 'number', id: true, generated: true, }) id?: number; @property({ type: 'string', required: true, }) password: string; // 定义BelongsTo关联 @belongsTo(() => User) userId: number; constructor(data?: Partial<UserCredentials>) { super(data); } }
补充说明
该问题核心原因是对LoopBack 4中HasOneRepositoryFactory的调用逻辑理解偏差——工厂函数需要先传入关联实体的ID,才能获取到可操作的关联仓库实例,而非直接传入创建参数,此问题与Github Issue #6964相关。
内容的提问来源于stack exchange,提问作者fudo
相关产品推荐
相关产品推荐

