【问题标题】:How can I use typescript generics for dynamic function arguments如何将打字稿泛型用于动态函数参数
【发布时间】:2018-08-21 05:32:57
【问题描述】:

我正在尝试围绕node's gRPC bindings 创建一个包装器 方法。我想在WrapperClient 上创建一个名为rpc 的方法,该方法调用底层GrpcClient 类的方法,但还要对methodrequest 进行类型检查> 论据。

这是一个示例,我将交叉发布到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 绑定是动态生成的,我不想维护一个可能的请求类型列表,这些类型在我重新生成绑定时可能会发生变化。

想法?

【问题讨论】:

    标签: node.js typescript generics grpc


    【解决方案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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-02-22
      • 2022-11-11
      • 2018-05-02
      • 1970-01-01
      • 2020-03-17
      • 2019-07-30
      • 2023-02-14
      • 2020-03-01
      相关资源
      最近更新 更多