如何为动态扩展用户类的函数添加JSDoc返回类型?
纯JS环境下用JSDoc标注动态继承类的返回类型
问题场景
在纯JavaScript环境中,我们需要为一个接收用户提供的类、返回继承自该类的新动态类的函数编写JSDoc,让VS Code这类支持类型提示的编辑器能同时识别:
- 原用户类的方法
- 动态类新增的方法
示例代码如下:
/** * Build a new class that extends the UserProvidedClass, and return that. * @param {class} UserProvidedClass * @returns ??? */ function createClientClass(UserProvidedClass) { return class ClientClass extends UserProvidedClass { bindServerSocket(socket) { this.server = socket; this.onConnect(); } onConnect() { super.onConnect?.(); if (DEBUG) console.log(`client connected`); } }; } // 使用示例 class CustomClass { testServer() { console.log(`instance has server:`, !!this.server); } } const ClientClass = createClientClass(CustomClass); const instance = new ClientClass(); // 编辑器应识别这是动态类新增的方法 instance.bindServerSocket(new WebSocket(`ws://localhost:800`)); // 编辑器应识别这是原CustomClass的方法 instance.testServer();
之前尝试的无效写法:
- 直接标注返回
UserProvidedClass:丢失动态类新增的方法提示 - 提取基类:受限于JS不支持多继承,无法同时关联两类方法
- 简单使用JSDoc泛型:仅能识别动态类新增方法,无法识别原类方法
可行解决方案
通过JSDoc泛型+交叉类型实现完整的类型提示,无需额外编写空代码:
步骤1:定义动态类新增方法的类型
先通过@typedef描述动态类添加的所有方法:
/** * @typedef {Object} ClientClassMixin * @property {(socket: WebSocket) => void} bindServerSocket - 绑定服务端socket的方法 * @property {() => void} onConnect - 连接触发的回调方法 */
步骤2:为函数添加泛型与交叉类型标注
修改createClientClass的JSDoc,用泛型捕获用户类的实例类型,再通过交叉类型合并原类与新增方法的类型:
/** * Build a new class that extends the UserProvidedClass, and return that. * @template T * @param {new () => T} UserProvidedClass - 用户提供的基类构造函数 * @returns {new () => T & ClientClassMixin} 返回继承自基类并包含新增方法的类构造函数 */ function createClientClass(UserProvidedClass) { return class ClientClass extends UserProvidedClass { bindServerSocket(socket) { this.server = socket; this.onConnect(); } onConnect() { super.onConnect?.(); if (DEBUG) console.log(`client connected`); } }; }
效果说明
@template T:声明一个泛型类型T,用于捕获用户传入类的实例类型new () => T:表示参数是能生成T类型实例的构造函数T & ClientClassMixin:交叉类型,合并原类实例类型与新增方法的类型new () => T & ClientClassMixin:表示返回的构造函数能生成同时具备两类方法的实例
此时VS Code等编辑器会正确识别:
instance.bindServerSocket和instance.onConnect来自动态类instance.testServer来自原CustomClass
内容的提问来源于stack exchange,提问作者Mike 'Pomax' Kamermans
相关产品推荐
相关产品推荐

