跳到主要內容
版本:4.x

TypeScript

從 v3 開始,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;
});
注意

這些類型提示不會取代輸入的適當驗證/清理。與往常一樣,切勿信任使用者輸入。

客戶端的類型

在客戶端,您可以重複使用相同的 ServerToClientEventsClientToServerEvents 介面

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