【问题标题】:Can't get the index type right on typescript instance method无法在打字稿实例方法上正确获取索引类型
【发布时间】:2021-06-16 22:50:57
【问题描述】:

我试图根据一些参数调用一个方法,但我无法编译它。

我遇到的错误:

test/unit/account-client/AccountGateway.spec.ts:59:10 - error TS2349: This expression is not callable.
  Each member of the union type '(<T = any>(params: GetRequestParams) => Promise<HttpResponse<T>>) | (<T = any>(params: PutRequestParams) => Promise<HttpResponse<T>>) | (<T = any>(params: PutRequestParams) => Promise<...>)' has signatures, but none of those signatures are compatible with each other.

59     when(x[httpVerb](anything())).thenResolve(success);
            ~~~~~~~~~~~

test/unit/account-client/AccountGateway.spec.ts:59:47 - error TS2345: Argument of type '{ statusCode: number; headers: {}; body: { id: string; }; }' is not assignable to parameter of type 'void'.

59     when(x[httpVerb](anything())).thenResolve(success);
                                                 ~~~~~~~


Found 2 errors.

代码首次尝试:

function whenAccountApiRequestSucceeds(httpVerb: 'get' | 'post' | 'patch') {
  const success = {
    statusCode: 200,
    headers: {},
    body: account,
  };
  when(httpClient[httpVerb](anything())).thenResolve(success);
}

第二次尝试,产生上述错误:

function whenAccountApiRequestSucceeds(httpVerb: 'get' | 'post' | 'patch') {
  const success = {
    statusCode: 200,
    headers: {},
    body: account,
  };
  const x = {
    get: httpClient.get,
    post: httpClient.post,
    patch: httpClient.patch,
  };
  when(x[httpVerb](anything())).thenResolve(success);
}

第三次尝试使用PickkeyofhttpClientHttpClient 类的一个实例:

 function whenAccountApiRequestSucceeds(
    httpVerb: Pick<keyof HttpClient, 'get' | 'post' | 'patch'>,
  ) {
    const success = {
      statusCode: 200,
      headers: {},
      body: account,
    };

    when(httpClient[httpVerb](anything())).thenResolve(success);
  }

这次我什至遇到了 lint 错误:

  • Type 'Pick&lt;keyof HttpClient, "get" | "post" | "patch"&gt;' cannot be used as an index type.ts(2538)
  • `键入“获取”| “帖子” | "patch"' 不满足约束 'number | "toString" | charAt" | "charCodeAt" | "concat" | "indexOf" | "lastIndexOf" | "localeCompare" | "match" |"replace" | "search" | "slice" | "split" | "substring" | "toLowerCase" | ... 31 更多 ... | "trimRight"'.'.ts(2344)'

仅作记录,本作品没有错误:

function whenAccountApiRequestSucceeds(_httpVerb: 'get' | 'post' | 'patch') {
  const success = {
    statusCode: 200,
    headers: {},
    body: account,
  };

  when(httpClient['get'](anything())).thenResolve(success);
  when(httpClient['post'](anything())).thenResolve(success);
  when(httpClient['patch'](anything())).thenResolve(success);
}

when()anything().thenResolve()ts-mockito 函数

我需要做什么才能使这个动态方法调用正常工作?

【问题讨论】:

  • 请考虑修改此处的代码以构成一个minimal reproducible example,当按原样放入The TypeScript Playground 之类的独立IDE 时,它会演示您的问题,或者如果失败,请考虑提供指向已配置Web 的链接演示该问题的 IDE 项目。这将允许想要回答的人开始研究解决方案,而不是首先花费时间来重现问题。祝你好运!

标签: typescript mapped-types


【解决方案1】:

你的第一次尝试是最接近正确的,所以让我们分解这个错误:

此表达式不可调用。

联合类型的每个成员 '((params: GetRequestParams) => Promise) | ((params: PutRequestParams) => Promise) | ((params: PutRequestParams) => Promise<...>)' 有签名,但这些签名都不兼容。

您的httpVerb 是联合类型。它可以是'get' | 'post' | 'patch' 中的任何一个。你会得到一个基于这个名字的函数httpClient[httpVerb]。该函数可以是get()post()patch()

这些函数有不同的参数——GetRequestParamsPutRequestParams。由于我们不知道它是哪一个,我们需要确保我们传递的任何参数都可以分配给联合的所有成员。错误表明这是不可能的。

declare const f: ((v: number) => void) | ((v: string) => void)

作为一个基本示例,如果您有一个变量f,它可以采用stringnumber,您不可能以类型安全的方式调用它。没有同时满足两个分支的参数。

我不知道这些类型是从哪里来的,所以我不知道GetRequestParamsPutRequestParams 之间的具体不兼容是什么。它可能只是方法名称?所以如果没有所有信息,我无法在这里给你最好的答案。

使用泛型可能会有所帮助:

function whenAccountApiRequestSucceeds<T extends 'get' | 'post' | 'patch'>(httpVerb: T) {

【讨论】:

  • @jcalz 我经常通过类型名称识别人们正在使用的包,我原以为这是节点 http 或其他东西,但实际上我用谷歌搜索了PutRequestParams,但我什么也没得到!所以这可能是一些自定义类型,其中类型本身很可能是坏的。
猜你喜欢
  • 1970-01-01
  • 2023-01-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-25
  • 1970-01-01
  • 2017-09-22
  • 1970-01-01
相关资源
最近更新 更多