TypeScript中继承WebSocket的ExtWebSocket为何无法在wss.clients.forEach使用
错误原因
ws库的wss.clients默认是Set<WebSocket>类型,仅包含ws官方定义的属性方法,你直接在forEach的参数中声明为自定义的ExtWebSocket属于非法的类型覆盖,会触发TS的类型校验报错。除此之外你还需要在WebSocket连接建立时主动给每个实例挂载isAlive属性,否则运行时也会出现属性不存在的异常。
解决方案
方案1:临时类型断言 + 手动挂载属性
首先在连接建立阶段初始化isAlive属性并监听pong事件更新存活状态:
import WebSocket, { WebSocketServer } from 'ws'; import express from 'express'; const app = express(); const server = app.listen(3000); const wss = new WebSocketServer({ server }); // 自定义扩展WebSocket接口 interface ExtWebSocket extends WebSocket { isAlive: boolean; } wss.on('connection', (ws: ExtWebSocket) => { // 初始化存活状态 ws.isAlive = true; // 收到pong响应时标记为存活 ws.on('pong', () => { ws.isAlive = true; }); // 其他业务逻辑 });
心跳检测阶段先做类型断言再使用:
setInterval(() => { wss.clients.forEach((ws) => { // 类型断言为扩展后的类型 const extWs = ws as ExtWebSocket; if (!extWs.isAlive) return extWs.terminate(); extWs.isAlive = false; extWs.ping(); }); }, 10000);
方案2:全局扩展ws模块类型(更推荐)
在项目中新增类型声明文件(如src/typings/ws.d.ts),直接扩展ws官方的WebSocket接口:
import 'ws'; declare module 'ws' { interface WebSocket { isAlive: boolean; } }
确保你的tsconfig.json的include配置包含了该类型声明文件,之后所有WebSocket实例默认都会携带isAlive属性,无需额外断言,心跳检测代码可以直接写:
setInterval(() => { wss.clients.forEach((ws) => { if (!ws.isAlive) return ws.terminate(); ws.isAlive = false; ws.ping(); }); }, 10000);
内容的提问来源于stack exchange,提问作者OmniOwl
相关产品推荐
相关产品推荐

