【问题标题】:How to safely assert a certain state from a typescript useReducer hook?如何从打字稿 useReducer 挂钩安全地断言某个状态?
【发布时间】:2021-06-04 09:49:30
【问题描述】:

假设我们有以下状态及其减速器操作

type User = {
    id: number
}

type LoginState = {
    user?: User,
    isLoggingIn: boolean,
    isLoggedIn: boolean,
    error?: Error
}

type LoginActions =
    | { type: 'START_LOGGING_IN' }
    | { type: 'SUCCESSFUL_LOG_IN', user: User }
    | { type: 'ERROR', error: Error }
    | { type: 'START_LOGGING_IN' }

如果我想从我的所有应用程序中使用这种状态,我肯定需要一些反应上下文解决方案。我不希望对这个问题使用任何外部依赖项。

但是,在some fsharp learning 之后,这种方法导致不可能的状态成为可能。例如,如果我们在 reducer 中出错,状态 isLoggedIn 可能会出错。

解决方案是使 LoginState 成为可区分的联合类型,但就我测试了 useReducer 的打字稿类型而言,强制我拥有一个类型中的所有属性,就像在示例中一样。

那么,这个问题通常是如何解决的呢?我知道我描述的示例是标准方法,但是,每当使用登录状态时,我必须在每个地方处理用户不存在的情况,这是我不想要的。我想要这个问题最安全的解决方案,所以请不要使用type assertions

如果我在某些断言中有错误,请纠正我,我对前端的东西很困惑:S

谢谢!

【问题讨论】:

    标签: reactjs typescript react-hooks


    【解决方案1】:

    最安全的方法是将LoginState 定义为仅包含有效reducer 状态的discriminated union。这使您能够定义仅处理那些为其设计的联合组成类型的函数。

    TS playground

    虽然通常这很麻烦,而且大多数时候开发人员对您问题中定义的LoginState 类型非常满意。

    【讨论】:

    • 嗯,我明白了,这种方法的问题是您仍然必须为每个状态编写大量无用的字段,这对于更复杂的状态实际上是不可扩展的。我想我是在要求某种状态机,例如 Xstate,但是,为什么反应文档推荐这种方法用于复杂状态?更重要的是,为什么 useReducer 不接受不同形状的状态联合?布尔标志从来没有真正代表状态的干净解决方案。不过,感谢您提供到操场的链接
    • 好吧,你可以通过接口继承来偷工减料,但对于复杂的状态,它很快就会变得一团糟。
    猜你喜欢
    • 1970-01-01
    • 2020-01-08
    • 2022-01-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-13
    • 1970-01-01
    • 2021-08-17
    相关资源
    最近更新 更多