You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 07:48:04