【问题标题】:How to get typescript error when using undeclared fields in useState's dispatch在 useState 的调度中使用未声明的字段时如何获取打字稿错误
【发布时间】:2021-07-04 20:30:16
【问题描述】:

理想情况下,我想知道为什么 ts 在下面的情况下不会抛出任何错误,以及是否有办法解决它以使其按预期工作。

尝试通过useState 的调度程序回调更新某些状态时,我预计会出现打字稿错误,但没有任何反应。这似乎是有效的:

  type State = {
    age?: number;
  };

  const [, setState] = useState<State>();

  setState((prev) => {
    // const copy = { ...prev };
    // this is a ts error;
    // copy.name = "scotty";
    // this is not
    return { ...prev, name: "scotty" };
  });

我希望 ts 在额外的未声明字段 name 上引发错误(我可以指定返回类型,但我不应该这样做,因为应该推断调度的参数 ((prevState: S) =&gt; S))。

我怎样才能输入这样我得到我期待的 ts 错误;此更新唯一允许的字段应该是在State 中定义/类型的字段。

最重要的是为什么这不起作用?

这里有一个codesandbox 来玩。

【问题讨论】:

  • 一般来说,Typescript 不认为额外的属性是一个问题。如果一个对象适合{age?: number},那么它就是State

标签: reactjs typescript react-hooks typescript-generics react-typescript


【解决方案1】:

Typescript 错误来自 typescript linter,它由您通常放在项目根目录的 tsconfig.json 文件定义。

并且您没有在您的codesandbox 中添加任何tsconfig.json

请将此 tsconfig.json 添加到您的根文件夹中,以获得您预期的 lint 错误:


{
  "compilerOptions": {
    "target": "es5",
    "lib": [
      "dom",
      "dom.iterable",
      "esnext"
    ],
    "allowJs": true,
    "skipLibCheck": true,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "noFallthroughCasesInSwitch": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "react-jsx"
  },
  "include": [
    "src"
  ]
}

将此添加到您的代码框后,我得到了预期的错误:

现在您可以在此错误中看到,它仍然允许您在不应添加的位置添加 name 属性。

为此,您只需将返回类型添加到您的 SetStateAction :


  useEffect(() => {
    
    setState((prev):State => { // <=== Add the State return type here
      // const copy = { ...prev };
      // copy.name = "scotty";
      return { ...prev, name: "scotty" };
    });
  }, []);

单线解决方案:

  useEffect(() => setState((prev) => ({ ...prev, age: 9 })), []);

【讨论】:

  • 嘿,我用我的 tsconfig 更新了代码框。这并不能解决我的问题/解释为什么 ts 在我期望的地方也没有抛出错误。在您的示例中,该错误是预期的,因为年龄不是可选类型并且未提供。我希望它在额外字段 name 上出错,因为它没有定义为 State 类型。
  • 还更新了代码 sn-ps 以通过将age 设为可选来突出显示这一点。
猜你喜欢
  • 2021-02-14
  • 1970-01-01
  • 1970-01-01
  • 2018-01-23
  • 2021-01-03
  • 2019-02-24
  • 2016-10-13
  • 2021-11-10
  • 2013-09-15
相关资源
最近更新 更多