首页 > 解决方案 > 泛型类方法和泛型类之间的打字稿语义差异

问题描述

我有点困惑为什么下面的示例代码在我使用类泛型时有效,但在我使用方法泛型时无效。

首先,我有简单RequestResponse课程:

abstract class BaseRequest {
  baseProperty: string;
}

class ChildRequest extends BaseRequest {
  childProperty: string;
}

abstract class BaseResponse<R extends BaseRequest> {
  data: any;
  request: R;
}

class ChildResponse extends BaseResponse<ChildRequest> {
}

为了使我的继承简单,我使用下面的泛型方法代码(注意该类不是泛型的,只有方法和扩展基类不需要泛型):

abstract class RequestClient {
  abstract request<RQ extends BaseRequest, RP extends BaseResponse<RQ>>(request: RQ): RP;
}


class ChildClient extends RequestClient {
  request(request: ChildRequest): ChildResponse {
    return undefined;   // just testing the code structure right now
  }
}

但是编译器会考虑ChildClient.request

TS2416: Property 'request' in type 'ChildClient' is not assignable to the same property in base type 'RequestClient'.
  Type '(request: ChildRequest) => ChildResponse' is not assignable to type '<RQ extends BaseRequest, RP extends BaseResponse<RQ>>(request: RQ) => RP'.
    Types of parameters 'request' and 'request' are incompatible.
      Type 'RQ' is not assignable to type 'ChildRequest'.
        Type 'BaseRequest' is not assignable to type 'ChildRequest'.
          Property 'childProperty' is missing in type 'BaseRequest'.

但是,使用类泛型可以正常工作:

abstract class RequestClient<RQ extends BaseRequest, RP extends BaseResponse<RQ>> {
  abstract request(request: RQ): RP;
}

class ChildClient extends RequestClient<ChildRequest, ChildResponse> {
  request(request: ChildRequest): ChildResponse {
    return undefined;
  }
}

我想避免类泛型,因为它开始创建类继承涓滴爆炸,我最终拥有大量无用的子类,只是为了让泛型方法正确编译。

为什么类泛型可以工作,但方法泛型不行?这里的语义区别是什么?

谢谢!

标签: typescriptgenerics

解决方案


因为在泛型方法示例中,您的子类违反了基类定义的约定。

基类承诺该类的一个实例允许调用者选择任何类型的请求和响应,但子类覆盖请求方法并限制契约:不,我只能发送一个 ChildRequest,而你只会返回一个儿童响应。

考虑以下情况:

const client: RequestClient = new ChildClient();

这是有效的,因为 ChildClient 扩展了 RequestClient。所以,由于客户端是RequestClient,你可以这样做

const response: MyResponse = client.request<MyRequest, MyResponse>(new MyRequest());

如果编译器接受了您想要的,将调用哪个方法?会发生什么?


推荐阅读