TypeScript
バージョン3から、Socket.IOはTypeScriptを第一級でサポートしています。
サーバーの型
まず、いくつかの型を宣言します
interface ServerToClientEvents {
  noArg: () => void;
  basicEmit: (a: number, b: string, c: Buffer) => void;
  withAck: (d: string, callback: (e: number) => void) => void;
}
interface ClientToServerEvents {
  hello: () => void;
}
interface InterServerEvents {
  ping: () => void;
}
interface SocketData {
  name: string;
  age: number;
}
そして、サーバーを作成する際にそれらを使用します
const io = new Server<
  ClientToServerEvents,
  ServerToClientEvents,
  InterServerEvents,
  SocketData
>();
その後、IDEの助けを借りて作業効率を上げましょう!
ServerToClientEventsインターフェースで宣言されたイベントは、イベントの送信とブロードキャストに使用されます
io.on("connection", (socket) => {
  socket.emit("noArg");
  socket.emit("basicEmit", 1, "2", Buffer.from([3]));
  socket.emit("withAck", "4", (e) => {
    // e is inferred as number
  });
  // works when broadcast to all
  io.emit("noArg");
  // works when broadcasting to a room
  io.to("room1").emit("basicEmit", 1, "2", Buffer.from([3]));
});
ClientToServerEventsインターフェースで宣言されたイベントは、イベントの受信に使用されます
io.on("connection", (socket) => {
  socket.on("hello", () => {
    // ...
  });
});
InterServerEventsインターフェースで宣言されたイベントは、サーバー間の通信に使用されます(socket.io@4.1.0で追加)。
io.serverSideEmit("ping");
io.on("ping", () => {
  // ...
});
最後に、SocketData型はsocket.data属性の型付けに使用されます(socket.io@4.4.0で追加)。
io.on("connection", (socket) => {
  socket.data.name = "john";
  socket.data.age = 42;
});
注意
これらの型ヒントは、適切な入力の検証/サニタイズに取って代わるものではありません。常として、ユーザー入力を信用しないでください。
クライアントの型
クライアント側では、同じServerToClientEventsおよびClientToServerEventsインターフェースを再利用できます
import { io, Socket } from "socket.io-client";
// please note that the types are reversed
const socket: Socket<ServerToClientEvents, ClientToServerEvents> = io();
同様に、ClientToServerEventsインターフェースで宣言されたイベントは、イベントの送信に使用されます
socket.emit("hello");
そして、ServerToClientEventsで宣言されたイベントは、イベントの受信に使用されます
socket.on("noArg", () => {
  // ...
});
socket.on("basicEmit", (a, b, c) => {
  // a is inferred as number, b as string and c as buffer
});
socket.on("withAck", (d, callback) => {
  // d is inferred as string and callback as a function that takes a number as argument
});
各名前空間のカスタム型
各名前空間は独自のイベントセットを持つことができるため、それぞれに型を提供することもできます
import { Server } from "socket.io";
// types for the main namespace
const io = new Server<ClientToServerEvents, ServerToClientEvents, InterServerEvents, SocketData>();
// types for the namespace named "/my-namespace"
interface NamespaceSpecificClientToServerEvents {
  foo: (arg: string) => void
}
interface NamespaceSpecificServerToClientEvents {
  bar: (arg: string) => void;
}
interface NamespaceSpecificInterServerEvents {
  // ...
}
interface NamespaceSpecificSocketData {
  // ...
}
const myNamespace: Namespace<
  NamespaceSpecificClientToServerEvents,
  NamespaceSpecificServerToClientEvents,
  NamespaceSpecificInterServerEvents,
  NamespaceSpecificSocketData
  > = io.of("/my-namespace");
myNamespace.on("connection", (socket) => {
  socket.on("foo", () => {
    // ...
  });
  socket.emit("bar", "123");
});
そして、クライアント側では
import { io, Socket } from "socket.io-client";
const socket: Socket<
  NamespaceSpecificServerToClientEvents,
  NamespaceSpecificClientToServerEvents
  > = io("/my-namespace");
socket.on("bar", (arg) => {
  console.log(arg); // "123"
});