任何类型的通用约束

时间:2018-04-20 17:56:55

标签: typescript

我必须开始展示我的代码才能解释我的问题。

我的通用类:

export class RpcPublisherMessage<T extends RpcPublisherRequest<T>> {
  constructor(public publisherRequest: T, public publishOptions: Options.Publish = {}, public timeoutMs?: number) {}
}

export class RpcPublisherRequest<T> extends RpcMessageData<T> {
  constructor(payload: T, private context: string) {
    super(payload);
  }

  public toBuffer(): Buffer {
    return Buffer.from(...);
  }
}

我的问题:

  public async dispatchMessage(rpcMessage: RpcPublisherMessage<any>): Promise<IRequestMessageResponse> {
    const message = rpcMessage.publisherRequest; // I can not call toBuffer() here
  }

这是我想要使用RpcPublisherMessage<any>的实例的地方。由于RpcPublishermessage有一个通用约束,我希望我能够在publisherRequest属性上调用toBuffer(),但显然我不是。

我试图解决这个问题:

我认为这可能是因为RpcPublisherMessage<any>中的任何一个也可能需要给出约束,但函数参数中的rpcMessage: RpcPublisherMessage<any extends RpcPublisherRequest<any>>之类的东西却没有用。然后VSCode说

  

[ts]来自导出类的公共方法的参数'rpcMessage'具有   或使用私人名称''。

我的问题:

为什么即使我为此属性指定了约束,我也无法在toBuffer()上调用publisherRequest

1 个答案:

答案 0 :(得分:1)

阐述我的评论作为答案。

除此之外:以下定义

export class RpcPublisherMessage<T extends RpcPublisherRequest<T>> { ... }

不是你想说的。从字面上看,您说参数T应该可以分配给RpcPublisherRequest<T>,其中第二个T 与第一个T相同payload 。除非您希望RpcPublisherRequest的{​​{1}}为RpcPublisherMessagepublisherRequest类型为RpcPublisherRequest,其payloadRpcPublisherMessage } publisherRequest是......:颤抖:除非你真的想要T的递归类型绑定,否则你应该改变那个定义。

如果你想要的是T应该是某些 RpcPublisherRequest<U>的{​​{1}},那么你就可以做到这一点:

U

这不再是递归类型绑定。

主要:你遇到的问题

export class RpcPublisherMessage<T extends RpcPublisherRequest<any>> { ... }

不应该是无法致电public async dispatchMessage( rpcMessage: RpcPublisherMessage<any> ): Promise<IRequestMessageResponse> { const message = rpcMessage.publisherRequest.toBuffer(); // no error const massage = rpcMessage.publisherRequest.toButter(); // also no error } 。相反,问题是toBuffer()被输入为rpcMessage.publisherRequest,这意味着您可以在没有投诉的情况下致电any。但你也可以在没有投诉的情况下致电toBuffer(),这很糟糕。并且您没有获得IntelliSense建议方法,因为toButter()类型可以具有任何属性,这是不好的。

这是因为any指定RpcPublisherMessage<any>T,它符合所有约束但不会给你任何类型提示。如果您想要更严格的约束,则可以指定anyT

RpcPublisherRequest<any>

那应该解决你的问题。如果您需要跟踪请求类型的特定有效负载类型,您可以始终使public async dispatchMessage( rpcMessage: RpcPublisherMessage<RpcPublisherRequest<any>> ): Promise<IRequestMessageResponse> { const message = rpcMessage.publisherRequest.toBuffer(); // no error const massage = rpcMessage.publisherRequest.toButter(); // error, yay! } 成为这样的通用方法:

dispatchMessage()

其中public async dispatchMessage<P>( rpcMessage: RpcPublisherMessage<RpcPublisherRequest<P>> ): Promise<IRequestMessageResponse> { const message = rpcMessage.publisherRequest.toBuffer(); // no error } 是您的通用有效负载类型。但你可能不需要那么远。

好的希望有所帮助;祝你好运!