【发布时间】:2019-03-06 23:13:58
【问题描述】:
我正在使用带有 React/Redux 的 Typescript。
网站访问者可以处于两种状态之一,LoggedIn 或 LoggedOut。我已经相应地构建了我的状态:
interface LoggedIn {
token: string,
user: Data.User
}
interface LoggedOut {
isLoading: boolean,
lastAttempFailed: boolean
}
type Store = LoggedIn | LoggedOut
来自 Haskell & Elm,感觉很自然。理论上,实现不可能访问undefined 或null 数据,因为它们只能访问与组件相关的状态(即一旦用户登录,组件就无法访问LoggedOut.isLoading )。
如何将其与mapStateToProps 集成?我有一个 Provider 组件供应我的商店。我希望某些组件只接受 LoggedIn 或 LoggedOut 实例 - 而不是整个商店。
理想情况下,这将由父组件进行类型检查和传递,例如:
class PrivateRouteComponent extends React.Component<OwnProps & ConnectedState, any> {
render() {
const { store, component, ...props } = this.props;
const Component = component;
switch (store.type) {
case "LOGGED_IN":
return <Route render={() => <Component store={store as Store.LoggedIn} {...props}/>}/>;
case "LOGGED_OUT":
return <Redirect to="/login"/>;
}
}
}
但这很hacky,通过道具传递商店感觉不习惯。 (另外:这也使得在react-router 中使用路由参数变得非常困难)。
对于这个问题有没有好的、类型安全的解决方案?干杯
【问题讨论】:
-
您能解释一下您认为您的解决方案有什么不妥之处吗?是您将
store转换为LoggedIn吗?如果您正确设置LoggedIn和LoggedOut的类型,则不会发生这种情况。此外,您说您不想传入整个存储区——但整个存储区是 LoggedIn/LoggedOut 的整个对象,所以这是不可避免的。你能澄清一下你的意思吗? -
基本上,在 Elm/Haskell 中,我可以保证我的主要状态将处于某种配置中,这样就不需要很多“如果状态是 x 则 y,否则为 z”。我正在尝试在 Typescript 中实现相同的保证,以避免不断的 switch 语句。
-
TypeScript 可以保证 store 是 valid,但这并不能消除代码中的任何条件,因为您需要根据它们的不同来处理它们状态。
-
这就是我想要解决的问题。在 Elm 中,我可以对联合类型进行模式匹配并相应地呈现不同的路由。然后将特定类型(例如
LoggedIn或LoggedOut)传递给组件,而不是整个联合。我怎样才能在 Typescript 中巧妙地做到这一点,而不通过道具(很多人不鼓励)传递商店?也许我需要与Context做点什么?我以前没用过。
标签: reactjs typescript redux type-safety