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;
});
注意
这些类型提示不会取代对输入的适当验证/清理。像往常一样,永远不要信任用户输入。
客户端类型
在客户端,您可以重用相同的 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"
});