能否使用JSDoc标注策略模式类工厂与链式API结构?
问题:如何用JSDoc标注动态继承的链式API结构?
我有这样的继承链:Chainable -> Strategy -> Actions,调用端通过Actions使用链式API:
await actionMaker() .action1() .action2() .run();
其中run方法来自Chainable,action1和action2可来自Strategy或Actions。动作方法会被推入数组,run通过Promise执行所有动作。实际代码结构如下:
// Chainable: class Chainable { enqueue(fn) { this.queue.push(fn); return this; } run() { return Promise_that_runs_everything; } } // Strategies: class platformStrategy1 extends Chainable { action1() { return this.enqueue(() => { /* action1 implementation for platform 1 */ }) } } class platformStrategy2 extends Chainable { action1() { return this.enqueue(() => { /* action1 implementation for platform 2 */ }) } } // Actions: function actionMaker(strategy) { class _Action extends strategy { action2() { return this.action1(); } } return new _Action(); } // Call site: await actionMaker(platformStrategy1) .action1() .action2() .run();
我可以根据运行平台传入不同策略,不同平台对应不同的动作实现。Actions中的方法仅调用Strategy的方法,策略类持有具体实现细节。除run返回执行动作的Promise外,所有方法均返回this。由于无法使用TypeScript,想询问:能否使用JSDoc对这类结构进行标注?
回答
当然可以用JSDoc标注这类动态继承的链式结构,下面是具体的标注方案,能让编辑器正确识别类型和链式调用提示:
1. 标注基类Chainable
/** * 基础链式操作类,提供队列管理和执行能力 * @class */ class Chainable { constructor() { /** @type {Function[]} 动作执行队列 */ this.queue = []; } /** * 将动作加入执行队列 * @param {Function} fn 要执行的动作函数 * @returns {this} 返回实例本身以支持链式调用 */ enqueue(fn) { this.queue.push(fn); return this; } /** * 依次执行队列中所有动作 * @returns {Promise<void>} 返回执行完成的Promise */ run() { return this.queue.reduce((promise, fn) => promise.then(fn), Promise.resolve()); } }
2. 标注策略类与接口
先定义策略的方法契约,再让具体策略实现:
/** * 平台策略接口,定义所有策略必须实现的方法 * @interface * @extends Chainable */ function PlatformStrategy() {} /** * 平台通用动作1 * @returns {this} 返回实例本身以支持链式调用 * @memberof PlatformStrategy */ PlatformStrategy.prototype.action1 = function() {}; /** * 平台1的具体策略实现 * @class * @extends Chainable * @implements PlatformStrategy */ class platformStrategy1 extends Chainable { /** * @returns {this} */ action1() { return this.enqueue(() => { /* 平台1的action1实现 */ }); } } /** * 平台2的具体策略实现 * @class * @extends Chainable * @implements PlatformStrategy */ class platformStrategy2 extends Chainable { /** * @returns {this} */ action1() { return this.enqueue(() => { /* 平台2的action1实现 */ }); } }
3. 标注actionMaker函数
通过模板参数处理动态继承的类型,让返回值同时包含策略方法和自定义动作:
/** * 创建动作实例,动态继承传入的平台策略类 * @template {typeof PlatformStrategy} T * @param {T} strategy 要继承的平台策略类 * @returns {InstanceType<T> & { action2(): InstanceType<T> }} 返回继承了策略的动作实例,包含额外的action2方法 */ function actionMaker(strategy) { class _Action extends strategy { /** * 自定义动作2,内部调用action1 * @returns {this} */ action2() { return this.action1(); } } return new _Action(); }
4. 调用端的类型提示验证
完成标注后,编辑器会自动识别链式调用的每个方法:
/** * 调用示例 */ async function demo() { await actionMaker(platformStrategy1) .action1() // 能识别来自platformStrategy1的action1 .action2() // 能识别来自_Action的action2 .run(); // 能识别来自Chainable的run }
关键标注要点
- 用
@interface定义策略的方法契约,确保所有策略类实现统一方法 - 通过
@template和InstanceType处理动态继承的类型,让actionMaker返回值同时包含策略方法和自定义动作 - 所有链式方法标注
@returns {this},保证编辑器识别链式调用的类型连贯性 - 用
@implements标记具体策略类实现了策略接口,增强类型检查的严谨性
内容的提问来源于stack exchange,提问作者shuckster
相关产品推荐
相关产品推荐

