打字稿:为什么打字机不能与以前的状态一起使用

Typescript: Why doesn't typeguard work with previous state

在使用打字稿制作简单的剪刀石头布游戏时,我遇到了一个我无法理解的交互。

const [gameState, setGameState] = useState<gameState>({
    choice: null,
    score: 0,
  });

function fetchScore() {
    let score = localStorage.getItem("score");
    if (typeof score === "string") {
      setGameState((prev) => ({ ...prev, score: 
      parseInt(score) })); // Typescript still thinks score can be null
    } 
}

parseInt 抛出一个错误,指出尽管有类型保护,分数仍可以设置为 null。

我做了一些乱七八糟的事情,发现它只在我使用 prev state 时发生。

 const [test,setTest] = useState(0);

 function fetchScore() {
    let score = localStorage.getItem("score");
    if (typeof score === "string") {
      setTest(parseInt(score))//Score is correctly guarded
    } 
  }

我目前通过将分数转换为字符串来处理它,但我想了解导致这种情况发生的原因?

那是因为您在回调函数中使用了分数。因此打字稿假定 score 变量可以在执行回调函数之前更改,并且 score 可能在回调函数内为 null。 解决方案: 我看到的最佳解决方案是使用 const 而不是 let.

const score = localStorage.getItem("score");

这样打字稿就知道以后不能更改分数。

您还可以检查 typeof score 回调函数内部,打字稿不会抱怨。我更喜欢 const。但这也会起作用。只是为了了解它是如何在这里工作的:

function fetchScore() {
  let score = localStorage.getItem("score");
  setGameState((prev: any) => {
    if (typeof score === "string") {
      // no complaining, checking inside of callback function
      return { ...prev, score: parseInt(score) };
    }
    return prev;
  });
}