打字稿未正确省略类型

时间:2019-10-17 09:33:11

标签: typescript

我正在尝试创建一个使用数字或字符串'last'并使用数组中相应元素的函数。

我处理输入为“ last”的情况。

我添加了一个简化的示例。 TS Playground

return state[i]行上出现错误。

我尝试将dispatch...移至(typeof i === 'number')的if块,但这也不起作用。

export function moveTo(i: number | 'last') {
  return (dispatch: Function, getState: ()=>string[]) => {
    const state = getState();
    if (i === 'last') {
      i = state.length - 1;
    }
    dispatch({
      index: i, //here i is shown to be number on hover
      effect() {
        return state[i]; // index expression is not of type number (shows as number | 'last')
      }
    });
  };
}

我想在if语句之后断言inumber,这样我就不必在效果函数中的任何地方都使用as number

2 个答案:

答案 0 :(得分:2)

由于i可能是stringnumber的一小部分,他们努力理解这种转换。一种解决方案是使用另一个变量:

export function moveTo(i: number | 'last') {
  return (dispatch: Function, getState: ()=>string[]) => {
    const state = getState();
    const index: number = (i == 'last') ? state.length - 1 : i;

    dispatch({
      index,
      effect() {
        return state[index];
      }
    });
  };
}

此外,同一变量具有多种类型(这可能会发生)是一件坏事,我建议使用-1而不是'last'来保持number类型。

答案 1 :(得分:1)

i回调中effect的类型未缩小,因为i被认为是函数moveTo的可变参数。

这意味着,在以后某个时间调用effect回调时,编译器无法确定i仍然具有number类型。结果,由if (i === 'last') {i = state.length - 1;}引起的类型保护失效,并且i在回调中获得了初始的number | 'last'类型。

那么TS何时将功能参数视为const

函数参数为implicitly treated as const,直到您在函数或嵌套函数中的某个位置对参数进行了分配。当参数是隐式const时,仍可以通过control flow analysis / type防护在嵌套函数表达式和箭头函数中访问其缩小的类型。因此,这个人为设计的example可以工作:

export function moveTo(i: number | 'last') {
  return (dispatch: Function, getState: () => string[]) => {
    if (i !== 'last')
      dispatch({
        index: i,
        effect() {
          return getState()[i];
        }
      })
  };
}

现在该怎么办?

您最好的选择可能是declare a new const variable(另请参阅@D。Nathanael的答案),它比回调中的as number产生更一致的类型。 Airbnb JavaScript Style Guide不建议您重新分配函数参数,因此您可以将i视为不可变的,从而有机会稍微clean up编写代码。