mega-crazy
mega-crazy

Reputation: 858

Saving more data on socket.io object in typescript

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.

Upvotes: 9

Views: 4283

Answers (6)

krunal
krunal

Reputation: 80

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
    }
  }
}

Upvotes: 0

IgnWombat
IgnWombat

Reputation: 96

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;

Upvotes: 4

harsh
harsh

Reputation: 51

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;

Upvotes: 5

NGS
NGS

Reputation: 367

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'

Upvotes: 4

John
John

Reputation: 21

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";

Upvotes: 2

Tsvetan Ganev
Tsvetan Ganev

Reputation: 8856

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

Upvotes: 7

Related Questions