为什么打字稿允许我覆盖空状态对象?

Joh*_*efs 5 state typescript ecmascript-6 reactjs

我将此代码视为将空状态定义为空,但是当我编写此代码时,没有任何错误.

export default class extends Component<Props, {}> {
  state = {
    foo: "bar"
  };
}
Run Code Online (Sandbox Code Playgroud)

这也不是错误:

export default class extends Component<Props, {}> {
  constructor(props) {
    super(props);
    this.setState({ foo: "bar" });
  }
Run Code Online (Sandbox Code Playgroud)

我在这里显然不了解TypeScript.如果我向传递的状态对象添加一个参数,则两个错误都显示状态差异.似乎{}没有提供任何防止被覆盖的警惕.我想从lint的角度确保状态总是被输入并作为参数传递或在React Component的扩展中作为null,我该如何设置它?

Exp*_*lls 2

在我看来,这需要一些挖掘才能弄清楚主要问题:为什么 TypeScript 允许您将具有属性的对象分配给声明为空对象的属性?

答案似乎有点埋藏在 TypeScript 规范中

实际上,类型的明显成员使其成为“Object”或“Function”接口的子类型,除非该类型定义的成员与“Object”或“Function”接口的成员不兼容。

也就是说,与类型用途{}相同。Object这允许您创建一个具有附加类型属性的对象,{}这就是您正在做的事情。请注意,this.state.foo不应允许这样做,因为该属性在 上不存在。同样,你也无法做到。foo{}this.state.foo =

至于为什么可以将具有未知属性的对象传递给ObjectsetState,这与 TypeScript 的类型兼容性有关。请参阅: https: //www.typescriptlang.org/docs/handbook/interfaces.html了解一种解释

请注意,我们的对象实际上具有比这更多的属性,但编译器仅检查是否至少存在所需的属性并与所需的类型匹配。

这也解释了:

对象字面量在将它们分配给其他变量或将它们作为参数传递时会受到特殊处理并进行过多的属性检查。

所以你的问题的答案似乎是,你在{}这里使用的地方,TypeScript 将它视为你正在使用的Object不是对象文字类型

我不确定如何强制执行没有属性的状态,但另一方面,我不确定这有什么用处。如果您想要一个没有属性的组件,请使用无状态或函数组件。