9

I usually used to do something like socket.username = username when not using typescript. But now i am and when i try to save it the same way it gives me the error

Property 'username' does not exist on type 'Socket'

I know this means i need to extend it, but i have tried it like so

interface Socket {
        username: any
}

But it did not help and i also tried this,

interface SocketIO {
        username: any
}

With no luck.

6 Answers 6

7

Just socket['username'] = username should do the trick.

If you want type safety and if you want to have autocompletion for the username property, you can extend the Socket interface.

interface ExtendedSocket extends Socket {
  username: string;
}

Then you can cast the original Socket to your custom type:

const mySocket = <ExtendedSocket>socket;
mySocket.username = 'user1'; // won't throw errors and autocomplete will work
Sign up to request clarification or add additional context in comments.

Comments

6

If you want to add extra information to the socket object, you can add this information to socket.data object which is declared with any in their declaration file

Below is a snippet from socket.d.ts file

/**
* Additional information that can be attached to the Socket instance and which will be used in the fetchSockets method
*/
data: any;

Comments

4

More generic way

Simply update module declaration like so:

declare module 'socket.io' {
    interface Socket {
        username: string
    }
}

Now you can use w/o any cast:

socket.username = 'Bob'

1 Comment

Doesn't work they way it is intended
4

In newer versions of Socket.IO, you can include this in the generic types. This can then be found in socket.data.

import { Server } from 'socket.io';

// Each event type should be a callback
interface ListenEvents {} // Events listened to on the server
interface ServerEvents {} // Events sent by the server
interface InterEvents {} // Events both listened to and sent by the server

interface SocketData {
    username: string;
}

const server = new Server<ListenEvents, ServerEvents, InterEvents, SocketData>(httpServer);

// ...
socket.data.username;

4 Comments

This doesn't work for me, even though it used to. Is this still how you're supposed to do this?
This should still be working. I haven't used socket.io in a few months, so the usage might've changed since. Note that this example usage would be server sided
Well the problem I'm having is that the client has no data field, i.e. I'm trying to extend the client socket, but it's not passing the extended information into the socket the server receives.
Here's a question I made describing my issue in more detail: stackoverflow.com/questions/76590830/…
2

This seems to accept a socket.username="John":

declare global {
  namespace SocketIO {
    interface Socket {
      username: any
    }
  }
}

But a nicer solution (IMHO) would be to extend the socket interface to your own socket:

interface ExtSocket extends SocketIO.Socket 
{
  username: string;
}

Then declare the socket itself as socket:ExtSocket; or use an ugly cast:

(socket as ExtSocket).username = "John";

Comments

0

I know this might come a bit late, but I wanted to share this here for anyone who might find it useful in the future.

import { Socket as OriginalSocket } from 'socket.io'

declare module 'socket.io' {
  interface Socket extends OriginalSocket {
    user: {
      id: number
      email: string
      // Add any other user properties you need
    }
  }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.