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

TypeScript报错:.filter无调用签名,如何移除房间内设备?

解决TypeScript中“.filter无调用签名”错误

问题场景

在处理设备断开连接逻辑时遇到TypeScript错误,具体提示:

This expression is not callable.
Type 'IDevice' has no call signatures.ts(2349)

完整代码

const rooms: Record<string, Record<string, IDevice>> = {};
interface IDevice {
    deviceId: string;
    deviceName?: string;
}
interface IRoomParams extends IDevice {
    userId: string;
}

interface ISendRequestParams {
    userId: string;
    options: any;
    requestId: string;
}

interface IReturnRequestParams {
    userId: string;
    data: any;
    requestId: string;
    error: any;
}

const joinRoom = ({ userId, deviceId, deviceName }: IRoomParams) => {
    if (!rooms[userId]) rooms[userId] = {};
    rooms[userId][deviceId] = { deviceId, deviceName };
    socket.join(userId);
    
    io.sockets.to(userId).emit('get-devices', {
        userId,
        participants: rooms[userId]
    });

    socket.on('disconnect', () => {
        console.log(`user left the room: roomId[${userId}], device[${deviceId}], deviceName[${deviceName}]`);
        rooms[userId] = rooms[userId]?.filter((id) => id !== deviceId);
        socket.to(userId).emit('device-disconnected', deviceName);
    });
};

问题原因

rooms的类型是Record<string, Record<string, IDevice>>,意味着rooms[userId]是一个键值对对象,而.filter()是数组专属方法,对象本身没有这个方法,因此TypeScript抛出调用签名不存在的错误。

解决方案

方案1:直接删除对象属性(推荐)

要移除指定设备,直接用delete操作符删除对应deviceId的属性即可,这是处理对象键值对最直接的方式:

socket.on('disconnect', () => {
    console.log(`user left the room: roomId[${userId}], device[${deviceId}], deviceName[${deviceName}]`);
    // 删除目标设备
    delete rooms[userId]?.[deviceId];
    // 可选:通知房间内其他用户更新设备列表
    socket.to(userId).emit('get-devices', {
        userId,
        participants: rooms[userId]
    });
    socket.to(userId).emit('device-disconnected', deviceName);
});

方案2:转数组过滤后转回对象

如果偏好类似数组的过滤逻辑,可以先把对象转为键值对数组,过滤后再转回对象:

socket.on('disconnect', () => {
    console.log(`user left the room: roomId[${userId}], device[${deviceId}], deviceName[${deviceName}]`);
    if (rooms[userId]) {
        // 对象转数组 → 过滤 → 转回对象
        rooms[userId] = Object.fromEntries(
            Object.entries(rooms[userId]).filter(([id]) => id !== deviceId)
        );
    }
    socket.to(userId).emit('device-disconnected', deviceName);
});

内容的提问来源于stack exchange,提问作者Jerry Seigle

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 21:10:25