【问题标题】:How do I return a Promise with this custom type in TypeScript?如何在 TypeScript 中返回具有此自定义类型的 Promise?
【发布时间】:2021-05-08 22:07:21
【问题描述】:

我不知道 ParsedAuthorizationResponse 是如何实现的,以及我如何以不同的方式设置它的值。最终,我想返回某个值/类型作为承诺。

我认为这会起作用,但它没有

let PAR; 
if (status === 'COMPLETED') { 
PAR = new ParsedAuthorizationResponse('AUTHORIZED')
} else throw new Error('Authorization failed')

return Promise<PAR>;
}

//Also tried this but didn't work

type ParsedAuthorizationResponse PAR = 'AUTHORIZED';
return new Promise<PAR>;

【问题讨论】:

  • 只需return PAR; - 无需承诺,您已经在async function 中,它已经完成了包装

标签: javascript typescript type-conversion typescript-generics return-type


【解决方案1】:

首先,正如@thedude 所说,因为你的函数已经是async,所以不需要返回一个Promise,无论你返回什么都会自动变成一个Promise。

现在回答:“如何返回ParsedAuthorizationResponse”。

从(部分)定义开始:

export type ParsedAuthorizationResponse =
  | IAuthResponse<
      { processorTransactionId: string },
      'AUTHORIZED' | 'CANCELLED' | 'SETTLING' | 'SETTLED'
    >

(我只用 ParsedAuthorisationResponse 的一个例子来做这个逻辑,希望你能做剩下的)

这表示它是一个IAuthResponse&lt;T, U&gt;,其中 T 是 { processorTransactionId: string } 而 U 是 'AUTHORIZED' | 'CANCELLED' | 'SETTLING' | 'SETTLED'

将这个插入 IAuthResponse 的定义给我们

type IAuthResponse<T, U extends TransactionStatus> = {
  processorTransactionId: string,
  transactionStatus: 'AUTHORIZED' | 'CANCELLED' | 'SETTLING' | 'SETTLED';
};

意思是ParsedAuthorizationResponse的例子是

{
  processorTransactionId: "any old string",
  transactionStatus: 'AUTHORIZED',
}

所以要从您的函数中返回它,请使用以下内容:

async authorize(
    request: RawAuthorizationRequest<ClientIDSecretCredentials, PayPalOrder>,
  ):ParsedAuthorizationResponse {
      //just imagine I'm gonna get a response that has a value of status in it
      const { status } = JSON.parse(await response)
      
      return {
          processorTransactionId: status, // or whatever
          transactionStatus: 'AUTHORIZED',
      };
  }

【讨论】:

    【解决方案2】:

    ParsedAuthorizationResponse 不是一个(这就是new 不起作用的原因),它是一个类型。在这种情况下,它是一堆不同的可能对象形状。一起来看看

      export type ParsedAuthorizationResponse =
      | IAuthResponse<
          { processorTransactionId: string },
          'AUTHORIZED' | 'CANCELLED' | 'SETTLING' | 'SETTLED'
        >
      | IAuthResponse<{ declineReason: string }, 'DECLINED'>
      | IAuthResponse<{ errorMessage: string }, 'FAILED'>;
    

    对,这告诉我们ParsedAuthorizationResponse 只是IAuthResponse 的三种不同参数化中的任何一种的同义词。不幸的是,在我们知道IAuthResponse 的样子之前,这并不能告诉我们太多。幸运的是,我们做到了:

    type IAuthResponse<T, U extends TransactionStatus> = T & {
      transactionStatus: U;
    };
    

    好的,这变得更具体了。 TransactionStatus 只是几个字面量字符串的同义词,而T &amp; { transactionStatus: U; } 是一个类型连词,意味着结果是一个类型,就像T 类型一样,加上一个字段transactionStatus 属于 U 类型(与 U extends TransactionStatus 一起被限制为我们称为 TransactionStatus 的一个或多个字符串)。

    那么IAuthResponse&lt;{ errorMessage: string }, 'FAILED'&gt; 是什么意思?好吧,看看IAuthResponse,它扩展为:

    { errorMessage: string } & { transactionStatus: 'FAILED' }
    

    相同
    { errorMessage: string; transactionStatus: 'FAILED' }
    

    这意味着ParsedAuthorizationResponse 实际上看起来像这样:

    type ParsedAuthorizationResponse =
          | { processorTransactionId: string; transactionStatus: 'AUTHORIZED' | 'CANCELLED' | 'SETTLING' | 'SETTLED' }
          | { declineReason: string; transactionStatus: 'DECLINED' }
          | { errorMessage: string; transactionStatus: 'FAILED' }
    

    所以,创建一个符合ParsedAuthorizationResponse 的对象真的很简单,它只是对象字面量:

    • 如果失败,它是一个带有transactionStatus: 'FAILED' 和任意errorMessage 字符串的对象
    • 如果它被拒绝,您有 transactionStatus: 'DECLINED' 和任意 declineMessage 字符串
    • 否则,它的transactionStatus 设置为'AUTHORIZED''CANCELLED''SETTLING''SETTLED' 之一,再加上一个processorTransactionId,这是一个字符串,我假设您与交易。

    你的例子最终会是这样的:

      async authorize(
        request: RawAuthorizationRequest<ClientIDSecretCredentials, PayPalOrder>,
      ): Promise<ParsedAuthorizationResponse> {
          // The response needs to contain status and transaction ID
          const { status, processorTransactionId } = JSON.parse(await response) as { status: string; processorTransactionId: string; }
          switch (status) {
            case 'COMPLETE':
              return { transactionStatus: 'AUTHORIZED', processorTransactionId };
            case 'VOIDED':
              return { transactionStatus: 'CANCELLED', processorTransactionId };
            // TODO: Fill in more cases here...
            default: 
              // Unknown status, hopefully shouldn't happen, but for the sake of
              // argument, let's pretend that failing the transaction is a reasonable
              // thing to do here, just to show how to return an error message
              return { transactionStatus: 'FAILED', errorMessage: 'Unknown status: ' + status };
          }
        }
    

    【讨论】:

    • 非常感谢您的精彩回答并花时间编写它!它清除了很多东西。
    【解决方案3】:

    返回一个 Promise 类型非常简单,与返回一个原始的 Promise 没有什么不同。

    您从async 函数返回的任何值都将被一个promise 包装,所以:

    const returnsANumber = async (): Promise<number> => {
      return 42
    }
    
    type Foo = {
      foo: true
    }
    
    const returnsAFoo = async (): Promise<Foo> => {
      return {
        foo: true
      }
    }
    

    TS playground

    在您的情况下,只需返回 ParsedAuthorizationResponse

    【讨论】:

    • 谢谢!我现在明白了承诺部分。你能帮我弄清楚如何设置 ParsedAuthorizationResponse 的值吗?因为我似乎无法弄清楚它是如何实现的,以及如何将其设置为“授权”或“拒绝”或类似的东西,然后在我的承诺中返回那种类型。
    • 如果我遵循你的代码,你应该返回PAR
    猜你喜欢
    • 2021-10-17
    • 1970-01-01
    • 1970-01-01
    • 2020-08-05
    • 2021-01-03
    • 1970-01-01
    • 2017-11-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多