如何更简洁创建类型安全JavaScript类以初始化Sequelize模型?
优化Sequelize模型类的异步初始化实现
核心问题
- 类构造器无法支持异步操作(截至2023年4月)
- Sequelize的
sync和create方法属于异步数据库操作,希望通过构造器传入属性完成模型定义与初始记录创建,但现有实现繁琐,TypeScript属性未赋值的处理不够优雅
现有实现
import type { Config } from '$lib/server/config.js'; import { Model, Sequelize, DataTypes } from 'sequelize'; import type { ModelDefined, InferAttributes, InferCreationAttributes, CreationOptional } from 'sequelize'; class CourseDescription extends Model<InferAttributes<CourseDescription>, InferCreationAttributes<CourseDescription>> { declare id: CreationOptional<number>; declare name: string; } export class Course { protected sequelize: Sequelize; protected Description: ModelDefined<InferAttributes<CourseDescription>, InferCreationAttributes<CourseDescription>>; public initComplete: Promise<boolean>; constructor(protected config: Config, name: string) { this.sequelize = new Sequelize(this.config.postgres_url); const desc = this.sequelize.define("CourseDescription", { id: { type: DataTypes.INTEGER, autoIncrement: true, primaryKey: true }, name: DataTypes.TEXT } ) // 临时赋值避免TypeScript"未赋值即使用"错误 this.Description = desc; this.initComplete = (async () => { await desc.sync(); await desc.create({ name }); return true; })(); } }
调用方式:
import config from './lib/server/config'; import { Course } from './lib/server/course' const m = new Course(config, "My Excellent Course"); await m.initComplete;
优化方案:使用静态异步工厂方法
利用静态异步方法替代构造器完成异步初始化逻辑,这是处理类异步初始化的标准做法,既解决TypeScript类型问题,又简化调用流程:
import type { Config } from '$lib/server/config.js'; import { Model, Sequelize, DataTypes } from 'sequelize'; import type { InferAttributes, InferCreationAttributes, CreationOptional } from 'sequelize'; class CourseDescription extends Model<InferAttributes<CourseDescription>, InferCreationAttributes<CourseDescription>> { declare id: CreationOptional<number>; declare name: string; } export class Course { protected sequelize: Sequelize; protected Description: typeof CourseDescription; // 私有构造器,强制通过静态方法创建实例 private constructor(protected config: Config, sequelize: Sequelize, descriptionModel: typeof CourseDescription) { this.config = config; this.sequelize = sequelize; this.Description = descriptionModel; } // 静态异步工厂方法,封装所有初始化逻辑 public static async create(config: Config, name: string): Promise<Course> { const sequelize = new Sequelize(config.postgres_url); // 关联模型与sequelize实例 CourseDescription.init( { id: { type: DataTypes.INTEGER, autoIncrement: true, primaryKey: true }, name: DataTypes.TEXT }, { sequelize, modelName: "CourseDescription" } ); await CourseDescription.sync(); await CourseDescription.create({ name }); return new Course(config, sequelize, CourseDescription); } }
优化后的调用方式
import config from './lib/server/config'; import { Course } from './lib/server/course' // 直接await静态方法获取实例,无需额外处理initComplete const m = await Course.create(config, "My Excellent Course");
优化点说明
- 消除冗余的
initComplete:通过静态异步方法直接返回初始化完成的实例,调用逻辑更直观 - 解决TypeScript类型问题:私有构造器确保实例只能通过工厂方法创建,避免属性未赋值的类型警告
- 模型定义更规范:使用
Model.init()替代sequelize.define(),符合Sequelize类继承模型的标准写法 - 逻辑更集中:所有异步初始化逻辑封装在静态方法中,类结构更清晰
内容的提问来源于stack exchange,提问作者ejkreboot
相关产品推荐
相关产品推荐

