typescript - 我可以从打字稿中的泛型类型中引用参数的类型吗?
问题描述
我正在尝试将类型检查添加到我通过 Web 套接字创建的 api 的前端。我省略了我认为与这个问题无关的复杂部分,但如果需要,我可以提供更多信息。我有一个服务器在 Web 套接字上侦听格式化为c|endpoint|command|data
字符串的消息,并将回复请求的数据。那部分工作得很好,但我想在客户端部分添加类型检查以帮助调试。每个端点都有多个命令,每个命令都采用自己的自定义数据对象,在发送之前将其字符串化,因此每个命令必须是一个函数,它接受套接字和数据并返回发回的数据。
interface Socket {
send(data: string): void
}
interface Command<T> {
(socket: Socket, data: T): string | Promise<string>
}
interface Endpoints {
[index: string]: {
[index: string]: Command<any>
},
test: {
hello: Command<{testarg: string}>
}
}
此示例有一个端点 ( test
) 和一个命令 ( hello
),该命令 () 将数据结构化为{testarg: string}
. 其他命令将具有不同的所需数据结构。
现在我有另一个函数从客户端发送命令,这是我希望进行类型检查的地方。
class ClientSocket {
// some parts not shown
socket!: WebSocket
call<T extends keyof Endpoints, K extends keyof Endpoints[T], U>(endpoint: T, command: K, data: U) {
// call the api: this.socket.send(`c|${endpoint}|${command}|${JSON.stringify(data)}`) and save the promise resolve for later resolution when we get a reply. I left that out since it's not exactly relevant.
return "promise for results of api call"
}
}
我想调用上面的三个参数,端点,命令和数据,对 Endpoints 接口进行类型检查,所以如果我尝试使用它会出现错误:call("test", "hello", {})
因为它缺少testarg
属性。我想出了如何检查前两个,所以我调用了一个有效的命令,但我不知道如何对数据 (U) 进行类型检查。
谢谢您的帮助。
解决方案
您需要编写一个小型类型包装器,以获取 Endpoints[T][K] 中命令的数据类型:
type CommandData<T extends keyof Endpoints, K extends keyof Endpoints[T]> = Endpoints[T][K] extends Command<infer TData> ? TData : never;
...
call<T extends keyof Endpoints, K extends keyof Endpoints[T]>(endpoint: T, command: K, data: CommandData<T, K>) {
// call the api: this.socket.send(`c|${endpoint}|${command}|${JSON.stringify(data)}`) and save the promise resolve for later resolution when we get a reply. I left that out since it's not exactly relevant.
return "promise for results of api call"
}
...
new ClientSocket().call("test", "hello", { testarg: "hello" }); // { testarg: string } is expected
但您可以将其缩短为:
...
call<T extends keyof Endpoints, K extends keyof Endpoints[T]>(endpoint: T, command: K, data: Endpoints[T][K] extends Command<infer TData> ? TData : never) {
...
有关 infer 关键字的更多信息,请参见https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html。
推荐阅读
- ios - 安装 GoogleMLKit 人脸检测时,CocoaPods 找不到 pod GoogleDataTransport 的兼容版本
- python - python根据模式拆分长输出字符串(无分隔符)
- javascript - 未捕获的 ReferenceError: 'a' 未在 HTMLButtonElement.onclick (gallery.html:1) 中定义
- vuetify.js - 将 v-card 分成 3 个不同百分比的部分
- angular - 使用 interval() 进行角度测试
- mysql - 无法使用 sql + node.js + virtual studio 代码连接到 sql server
- java - 简单的java arraylist编程问题
- node.js - 在 Mongo shell 中删除 MongoDB 集合中的所有文档
- c# - 代码战任务。如何通过条件找到简单的平方数?
- javascript - Material UI 自动完成与文本字段中的头像