我正在尝试围绕node's gRPC bindings创建一个 wrapper 方法。我想在rpc
上创建一个称为WrapperClient
的方法,该方法调用基础GrpcClient
类上的方法,但还要键入方法和< strong>请求参数。
以下是我将交叉发布到TS playground的示例。
type ReqA = { type: 'a' }
type ReqB = { type: 'b' }
class GrpcClient {
findA(request: ReqA) { };
findB(request: ReqB) { };
}
class WrapperClient {
rpc<GrpcClient, TMethod extends keyof GrpcClient>(client: GrpcClient, method: TMethod, req: any) {
}
}
const grpcClient = new GrpcClient()
const client = new WrapperClient()
// This works
grpcClient.findA({ type: 'a' }) // correct
grpcClient.findB({ type: 'b' }) // correct
// This doesn't.
// It Matches the method name. That's good.
// But it does not check the request type.
client.rpc(grpcClient, 'findA', 1) // should fail
client.rpc(grpcClient, 'findB', 1) // should fail
client.rpc(grpcClient, 'findC', 1) // double fail, the method check works though
我可以使用extends keyof
通用表达式来对方法名称进行类型检查。我无法输入检查请求参数。
我可以将联合硬编码为请求参数类型。
rpc<GrpcClient, TMethod extends keyof GrpcClient>(client: GrpcClient, method: TMethod, req: ReqA | ReqB) {
gRPC绑定是动态生成的,我不希望维护一个在重新生成绑定时可能会更改的可能请求类型的列表。
有想法吗?
答案 0 :(得分:1)
您可以使用conditional type来确定请求类型:
type ReqA = { type: 'a' }
type ReqB = { type: 'b' }
class PeopleServiceClient {
findA(request: ReqA) { };
findB(request: ReqB) { };
}
class WrapperClient {
rpc<PeopleServiceClient, TMethod extends keyof PeopleServiceClient>(
client: PeopleServiceClient, method: TMethod,
req: PeopleServiceClient[TMethod] extends (arg: infer T) => void ? T : never) {
}
}
const grpcClient = new PeopleServiceClient()
const client = new WrapperClient()
grpcClient.findA({ type: 'a' }) // correct
grpcClient.findB({ type: 'b' }) // correct
client.rpc(grpcClient, 'findA', {type: 'a'}) // correct
client.rpc(grpcClient, 'findA', {type: 'b'}) // fails
client.rpc(grpcClient, 'findA', 1) // fails
client.rpc(grpcClient, 'findB', 1) // fails
client.rpc(grpcClient, 'findC', 1) // fails