Sequelize+GraphQL中user.password与user.id类型错误解决问询
GraphQL + Sequelize登录功能的TypeScript类型错误解决
问题概述
在实现用户登录功能时遇到两个TypeScript错误:
- 访问
user.password或user.id时触发错误:Property 'password' does not exist on type 'Model<any, any>' - 修改User Model的TypeScript接口定义后,出现
Cannot find name 'UserAttributes'错误
解决方案
1. 初始类型错误的根源
Sequelize默认生成的Model类型为Model<any, any>,TypeScript无法识别自定义的id、password等属性,必须给Model定义明确的类型接口以实现正确的类型推断。
2. 修正User Model的类型定义
修改Model时的错误是引用了未定义的UserAttributes接口,只需将未定义的接口名替换为已定义的类型,或直接将接口命名为UserAttributes即可。以下是正确的Model代码:
import { DataTypes, Model, Optional } from 'sequelize'; import sequelize from '../config/sequalize'; // 定义用户属性,createdAt和updatedAt为可选,因为Sequelize会自动生成 interface UserAttributes { id: number; email: string; password: string; createdAt?: Date; updatedAt?: Date; } // 定义实例类型:继承Model,同时指定创建实例时可省略id(自增主键) interface UserInstance extends Model<UserAttributes, Optional<UserAttributes, 'id'>>, UserAttributes {} const User = sequelize.define<UserInstance, UserAttributes>( 'user', { id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true, }, email: { type: DataTypes.STRING, allowNull: false, unique: true, }, password: { type: DataTypes.STRING, allowNull: false, }, }, { timestamps: true, } ); export default User;
3. 修正GraphQL Resolver中的类型与细节
修正后User.findOne会返回UserInstance | null,TypeScript可正确识别user.password和user.id。同时修正错误提示的描述,并确保JWT payload的类型匹配:
// ... 其他导入代码不变 // 修正JWT payload接口命名,提升可读性 interface JwtPayload { id: string; } const createRefreshToken = (payload: JwtPayload) => { return jwt.sign(payload, config.JWT_SECRET, { expiresIn: '7d', }); }; // ... UserType定义不变 const mutation = new GraphQLObjectType({ name: 'Mutation', fields: { login: { type: UserType, args: { email: { type: GraphQLString }, password: { type: GraphQLString }, }, async resolve(parent, args, res) { const user = await User.findOne({ where: { email: args.email } }); if (!user) { throw new Error('User not found'); // 修正错误提示内容,原提示逻辑不符 } const isMatch = await bcrypt.compare(args.password, user.password); if (!isMatch) { throw new Error('Invalid password'); } // 将number类型的id转为string,匹配JwtPayload接口要求 const refresh_token = createRefreshToken({ id: user.id.toString() }); res.cookie('refreshtoken', refresh_token, { httpOnly: true, path: '/user/refresh_token', maxAge: 7 * 24 * 60 * 60 * 1000, // 7天有效期 }); return { msg: 'Login success!' }; }, }, }, });
额外注意事项
- 使用
Optional<UserAttributes, 'id'>是因为创建用户时无需手动传入自增的id字段,Sequelize会自动生成。 - 若使用Sequelize v6及以上版本,类型定义已内置,无需额外安装
@types/sequelize。 - 确保
sequelize数据库连接配置正确,且依赖包已安装完整。
内容的提问来源于stack exchange,提问作者zuzuzuu
相关产品推荐
相关产品推荐

