为啥打字稿允许我覆盖一个空的状态对象?

Posted

技术标签:

【中文标题】为啥打字稿允许我覆盖一个空的状态对象?【英文标题】:Why does typescript allow me to override an empty state object?为什么打字稿允许我覆盖一个空的状态对象? 【发布时间】:2019-07-14 08:34:30 【问题描述】:

我将这段代码读作将状态定义为空,但是当我编写这段代码时,没有任何错误。

export default class extends Component<Props, > 
  state = 
    foo: "bar"
  ;

这也不会出错:

export default class extends Component<Props, > 
  constructor(props) 
    super(props);
    this.setState( foo: "bar" );
  

我显然不了解这里的 TypeScript。如果我向传递的状态对象添加一个参数,两个错误都会显示状态差异。似乎 没有提供任何防止被覆盖的保护措施。我想从 linting 的角度确保始终输入状态并在 React 组件的扩展中作为参数或 null 传递,我该如何设置?

【问题讨论】:

【参考方案1】:

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

答案似乎埋在TypeScript spec a bit

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

也就是说,出于类型目的,Object 被视为相同。这允许您创建一个具有 类型的附加属性的对象,这就是您正在做的事情。请注意,this.state.foo 不应被允许,因为 foo 属性在 上不存在。同样,您将无法执行this.state.foo =

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

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

这也说明了:

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

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

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

【讨论】:

这很好,如果你不想强制执行任何状态,我想答案是你应该使用一个函数。但如果你愿意,你可以做Foo extends Component&lt;Props, null&gt;。我只是喜欢某种 linter 错误,它告诉你如果你不定义状态,你应该重构一个函数或明确定义它。整个隐式重载对我来说似乎是一种反模式。 参见:typescriptlang.org/docs/handbook/type-compatibility.html——TypeScript 在这里做出了一些决定,主要是为了与 javascript 兼容。这不是隐式重载,它实际上是 显式 多余的属性检查。

以上是关于为啥打字稿允许我覆盖一个空的状态对象?的主要内容,如果未能解决你的问题,请参考以下文章

如何覆盖打字稿中的属性?

是否可以用打字稿覆盖不同 typeNum 的模板?

如何在打字稿中对模型接口进行单元测试?

在 sonarqube 中使用 jest 和旁观者覆盖组件方法的 Angular 打字稿测试

如何覆盖从打字稿中其他文件导入的功能?

typescript Ionic 1(Angular 1.x)后退按钮覆盖 - 打字稿版本