【问题标题】:Allow temporarily empty object for a typed state允许输入状态的临时空对象
【发布时间】:2022-01-25 09:09:19
【问题描述】:

我来自 JS 背景,现在正在学习 Typescript。我无法克服这个问题。 我有一个非常特殊类型的状态,我知道我将来需要使用它:

type NotificationValuesType = {
  channel: string
  for: NotificationUsageTypes
  id: string
  type: NotificationTypes
  workspace: string
}[]

我正在像这样设置我的 React 状态:

  const [dropdownsState, setDropdownsState] = useState<NotificationValuesType>([])

问题是,最初我现在只能typeid,当用户选择它们时,我可以通过一系列下拉列表收集所有其余的道具,事件触发,然后用一个填充状态一次下拉,所以在某些时候,它只会是: [{id: "id", type: "type", channel: "channel"}] 在下一个事件中,它将是 [{id: "id", type: "type", channel: "channel", workspace: "workspace"}] 和一个步骤和状态更新,以了解声明类型中的所有道具。

我不明白的是如何告诉 Typescript 在我知道所有道具之前不要对我大喊大叫,并确保我将来会知道所有需要的道具。

  • 我绝对不能将这些道具设为可选,因为它们
    不是可选的。
  • 还尝试将状态类型设置为NotificationValuesType | [],但打字稿一直在大喊大叫
  • 我了解了类型断言并猜测它应该会有所帮助,但找不到任何在状态上使用它的示例。我能做点什么吗 喜欢const [dropdownsState, setDropdownsState] = useState as &lt;NotificationValuesType&gt;([]) ???

感谢您一直阅读到最后! =)

【问题讨论】:

    标签: reactjs typescript types typeerror


    【解决方案1】:

    我绝对不能让这些道具中的任何一个成为可选的,因为它们 不是可选的。

    也许不是在你完成后,而是在你构建它的过程中,如果值需要是undefined,那么类型需要反映这一点。因此,您很可能希望状态变量具有可选属性,然后您通过步骤填写它,一旦您验证了它就在那里,您可以将它分配给具有属性类型的变量都是强制性的。

    有一个名为 Partial 的辅助类型,它将接收一个类型并生成一个新的类型,该类型的属性是可选的。

    // Note: this type is just the individual object, not the array that you have
    type Example = {
      channel: string
      for: NotificationUsageTypes
      id: string
      type: NotificationTypes
      workspace: string
    }
    
    const [dropdownsState, setDropdownsState] = useState<Partial<Example>[]>([])
    
    // Later on, once you've verified that all the properties exist you can 
    // assert that it's done. I don't know exactly what your verification 
    // code will look like, but here's an example
    if (dropdownsState.every(value => {
      return value.channel && value.for && value.id && value.type && value.workspace
    })) {
      const finishedState = dropdownsState as Example[];
      // do something with the finished state
    }
    

    编辑:正如 cmets 中所指出的,如果您使用 type guard,那么 typescript 可以缩小类型范围并让您不必重新分配它:

    if (dropdownsState.every((value): value is Example => {
      return value.channel && value.for && value.id && value.type && value.workspace
    })) {
      // Inside this block, typescript knows that dropdownsState is an Example[]
    
    }
    

    【讨论】:

    • 考虑写dropdownsState.every((value): value is Example =&gt; { return value.channel &amp;&amp; value.for &amp;&amp; value.id &amp;&amp; value.type &amp;&amp; value.workspace; },这样就不需要类型断言和临时的了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-07-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-06
    相关资源
    最近更新 更多