如何让IDE识别作为参数传递的类对象的属性与方法
问题原因
你现在的代码无法触发编辑器自动补全,核心原因是没有给编辑器提供足够的静态类型信息:
- 你写的
Message类所有属性都在init()方法里动态挂载,编辑器做静态代码扫描时,不会深度执行方法逻辑推断this上绑定的属性,根本不知道Message实例有哪些属性和方法 - 你的
.on()方法的JSDoc只标注了回调是FUNCTION类型,没有明确说明不同事件名对应的回调参数类型,编辑器无法推导传入回调的参数结构
解决方案
不需要额外引入TypeScript,只用标准JSDoc做类型标注就能实现和discord.js一致的自动补全效果,分两步改:
1. 重构Message类,显式声明所有实例属性
把所有在init()里挂载的属性提前在类顶层声明,加上对应的类型标注,让编辑器可以直接识别实例的属性结构:
class Message { /** * 消息文本内容 * @type {string} */ content /** * 消息所属频道 * @type {{ * id: string, * send: (content: string) => Promise<any> * }} */ channel /** * 消息发送者信息 * @type {{ * bot: boolean, * username: string, * tag: string, * identifier: string, * id: string, * avatar: string * }} */ author /** * 消息所属服务器 * @type {{ id: string }} */ guild /** * 消息发送时间戳 * @type {string} */ timestamp /** * 初始化消息实例 * @param {Record<string, any>} d 网关返回的原始消息数据 * @param {string} token 机器人鉴权令牌 * @returns {Message} */ init(d, token) { this.content = d.content this.channel = { id: d.channel_id, send: (content) => sendMessage(d.channel_id, token, content) } this.author = { bot: d.author.bot ?? false, username: d.author.username, tag: `${d.author.username}#${d.author.discriminator}`, identifier: d.author.discriminator, id: d.author.id, avatar: `https://cdn.discordapp.com/avatars/${d.author.id}/${d.author.avatar}.gif` } this.guild = { id: d.guild_id } this.timestamp = d.timestamp return this } }
2. 给.on()方法加泛型类型标注,明确回调参数类型
通过JSDoc定义事件名和对应回调参数的映射关系,让编辑器可以根据用户传入的事件名自动推导回调参数类型:
/** * 支持监听的事件类型 * @typedef {'message'} ClientEvent */ /** * 事件对应回调的参数映射 * @template {ClientEvent} T * @typedef { * T extends 'message' ? (message: Message) => void : * (...args: any[]) => void * } EventCallback */ class Client { // ... 你已有的其他Client类代码 /** * 监听网关事件 * @template {ClientEvent} T * @param {T} event 要监听的事件名 * @param {EventCallback<T>} callback 事件触发时执行的回调 */ on(event, callback) { ws.on('message', (data) => { const payload = JSON.parse(data) const { t, d } = payload const eventName = event.toLowerCase() switch(eventName) { case "message": if (t === "MESSAGE_CREATE") { const message = new Message().init(d, this.token) callback(message) } break } }) } }
扩展说明
后续新增其他事件时,只要在ClientEvent的typedef里补充事件名,在EventCallback的条件类型里补充对应事件的回调参数类型即可。比如新增ready事件:
/** * @typedef {'message' | 'ready'} ClientEvent */ /** * @template {ClientEvent} T * @typedef { * T extends 'message' ? (message: Message) => void : * T extends 'ready' ? () => void : * (...args: any[]) => void * } EventCallback */
改完之后,用户调用client.on('message', (msg) => {})时,编辑器会自动识别msg是Message类型,所有你标注过的属性、方法都会正常出补全提示,和discord.js的效果完全一致。
内容的提问来源于stack exchange,提问作者Gavin Holmes
相关产品推荐
相关产品推荐

