假设我有这个代码——我知道它是错误的。
enum SocketClient {
PLAYER_LOGIN = "player:login",
PLAYER_LOGOUT = "player:logout",
}
enum SocketClientPayload {
PLAYER_LOGIN = { user: string; pass: string};
PLAYER_LOGOUT = { uuid: string;}
}
type wsMessage = {
event: typeof SocketClient;
payload: SocketClientPayload[SocketClient];
};
我希望底部的payload
与我为传入的SocketEvent
指定的任何内容绑定,以便键入每个SocketEvent
的payload
。有没有一种方法可以实现动态表单类型?
您可以为此使用映射类型。例如:
enum SocketClient {
PLAYER_LOGIN = "player:login",
PLAYER_LOGOUT = "player:logout",
}
type SocketClientPayload = {
[SocketClient.PLAYER_LOGIN]: { user: string; pass: string; };
[SocketClient.PLAYER_LOGOUT]: { uuid: string; };
};
type wsMessage<T extends SocketClient> = {
event: T;
payload: SocketClientPayload[T];
};
let test: wsMessage<SocketClient.PLAYER_LOGOUT> = {
event: SocketClient.PLAYER_LOGOUT,
payload: { uuid: 'test' }
};
TypeScript游乐场
通过使wsMessage
类型通用,您可以让它根据SocketClient
枚举的哪个成员来实例化它,从而确定要使用哪个有效负载类型
请注意,TypeScript在这样使用时不会推断泛型类型,这就是为什么我必须指定我创建的test
变量的类型为SocketClient.PLAYER_LOGOUT
,尽管理论上可以根据event
属性的值来确定。但是TypeScript在泛型函数中使用时可以推断出这一点。例如:
function processPayload<T extends SocketClient>(message: wsMessage<T>) {
// Do something
}
// TypeScript can see the argument is of type `wsMessage<SocketClient.PLAYER_LOGIN>` based on its `event` property, and it infers the generic type of the function from that.
processPayload(
{
event: SocketClient.PLAYER_LOGIN,
payload: { user: 'test', pass: 'test' },
},
);
TypeScript游乐场