打字稿中的联合返回类型

时间:2020-08-24 19:18:25

标签: javascript reactjs typescript react-hooks

尝试以可能无法设计的方式使用打字稿,需要一些指导:

我在react中做了一个useGet钩子,该钩子返回以下类型之一:

type Res<T> = [T, false, false] | [null, true, false] | [null, false, true]

当我像这样返回钩子结果时:

return [data, loading, error]

我得到以下错误:

Type '[T | null, boolean, boolean]' is not assignable to type 'Res<T>'.
  Type '[T | null, boolean, boolean]' is not assignable to type '[null, true, false]'.
    Type 'T | null' is not assignable to type 'null'.
      Type 'T' is not assignable to type 'null'.ts(2322)

我不明白这里是什么问题。我希望以后对if (!loading)进行检查,然后再输入打字稿,才能将data解释为T

也许我问得太多...

谢谢!

完整钩子代码:https://gist.github.com/ELI7VH/8321bc65e213665569e9c97684f21255

2 个答案:

答案 0 :(得分:3)

loadingerror均为boolean类型。这意味着(就类型系统而言),两者都可以是true,而Res<T>不允许。您可能有防止这种情况的逻辑,但是类型系统并不能真正知道这一点。

如果要在联合中强健地键入这些元组,我认为您应该使用运行时逻辑显式返回每种情况。

  if (data) {

    // Has data, done loading, no error.
    return [data, false, false]

  } else if (error) {

    // No data, done loading, there was an error.
    return [null, false, true]

  } else {

    // No data, loading in progress, no error yet.
    return [null, true, false]

  }

现在,打字稿可以验证所有条件分支都返回正确的元组。


或者您可以只键入Res作为[T | null, boolean, boolean],但这具有无法从一个成员推断其他成员的缺点。

这意味着您不能这样做:

declare const res: Res<any>
if (res[1]) { // typescript now knows this tuple is: [null, true, false]
  const a = res[0] // typescript knows this is null
  const b = res[2] // typescript knows this is false
}

但是您可以采用第一种方法。

Playground

答案 1 :(得分:2)

检查(!loading)是否会导致打字稿将load解释为false。但这不会改变它解释数据的方式。

void USART1_RX_IRQHandler(void)
{
    if(USART1->STATUS & (1 << 7)) {   // if RX buffer contains valid data
                      rx_char = USART1->RXDATA;       // store the data
                    }
                    if(rx_char) {                     // if we have a valid character
                      if(USART1->STATUS & (1 << 6)) { // check if TX buffer is empty
                        USART1->TXDATA = rx_char;     // echo received char
                        rx_char = 0;                  // reset temp variable
                      }
                    }


}