#Socket.io type declaration merge

3 messages · Page 1 of 1 (latest)

mellow flower
#

I am trying to perform a declaration merge for Socket.io's Socket class so I can have some custom type information in the handshake auth object.

I have successfully done this for Express like so:

import { Request } from "express";

declare module 'express-serve-static-core' {
    interface Request {
        user?: {
            id: string,
            nickname: string,
            email: string,
            session_id: string
        }
    }
}

Now in my nestjs controllers, I can access req.user.nickname for example with type support.

I want to do something similar for my websocket gateways (socket.io platform). I googled a bit and came up with this:

import { Socket } from "socket.io"

declare module 'socket.io' {
    interface Socket {
        handshake: {
            auth: {
                user?: {
                    id: string,
                    nickname: string,
                    email: string,
                    session_id: string
                }
            }
        }
    }
}

However, in my gateways, when I do client.handshake.auth, there is no user type there, so this declaration merge is not working.

I didn't need to add anything to tsconfig.json for express, so I didn't think I'd need to do it for socket.io. However, I did try changing typeRoots to be:

"typeRoots": [
  "./node_modules/@types",
  "./src/util/type-ext" // where my custom declaration files live
]

This however, still did not work.

Has anyone managed to successfully do a declaration merge for socket.io to have custom properties on the Socket#Handshake interface? Thanks.

mellow flower
#

Well I've come up with this so far:

import { IoAdapter } from "@nestjs/platform-socket.io";
import { Server, ServerOptions } from "socket.io";
import { DefaultEventsMap } from "socket.io/dist/typed-events";

export interface SocketData {
    user?: {
      id: string,
      nickname: string,
      email: string,
      session_id: string
    }
}

export class CustomIoAdapter extends IoAdapter {
    createIOServer(port: number, options?: ServerOptions) {
        return new Server<DefaultEventsMap, DefaultEventsMap, DefaultEventsMap, SocketData>(
            this.httpServer && port === 0 ? this.httpServer : port, 
            options
        );
    }
}

And have elected to use this custom adapter in my main.ts, app.useWebSocketAdapter(new CustomIoAdapter());

But unfortunately, I'm still a missing a key piece. In my handler, I just have client: Socket, and client.data is not typed - probably because somewhere the types I've specified in my custom adapter are erased.

Hmmph.