我正在使用流,我想让我的减速器更安全。我发现这条评论提出了一个解决方案,我觉得这个解决方案很好,很适合我的代码库:https://github.com/reduxjs/redux/issues/992#issuecomment-191152574
我正试图使用%checks
关键字将其移植到流中,但它不起作用。
我的代码:
export type Action<T> = {
type: string,
payload: T,
};
interface ActionCreator<P> {
type: string;
(payload: P): Action<P>;
}
export function actionCreator<P>(type: string): ActionCreator<P> {
return Object.assign((payload: P) => ({ type, payload }), { type });
}
export function isActionOfType<P>(
action: Action<any>,
creator: ActionCreator<P>
): boolean %checks {
return action.type === creator.type;
}
每当我在类似的减速器功能中使用它时
(...)
case isActionOfType(action, getArticles):
// action.payload is still any
(...)
我做错什么了吗?有可能让这个打字脚本解决方案在流中工作吗?或者我应该使用不同的方法?如果是,你有什么建议?
在TypeScript中,您不会使用case
语句,而是使用if
语句。
在Redux中没有必须使用case语句的规则,事实上,我们不再鼓励在TypeScript中使用这种模式,而是支持带有类型保护的if
语句。
所以我想你可以试试。很抱歉,我不能在流方面真正帮助你,我只能就如何推荐TypeScript的现代模式给出一般建议,并希望这些模式能反映在流中。
一般来说,您还可以查看官方的Redux工具包,它带来了所有这些抽象。它只是部分流类型的,但这些类型可能已经满足了您的需求,或者您甚至可以改进它们。
如果您构建了一个类型泛型,该泛型具有一个与有效负载类型链接的类型字符串引用,则可以使用切换用例。我不知道像你这样的用例是否可行,因为如果条件是针对case
中的string
s而不是boolean
s进行测试,那么切换用例几乎是它们自己的。
下面的解决方案利用了类型细化,因此基于您编写的条件JS,流将推断有效负载结构。这里需要注意的是,在action
参数中,您必须添加所有可能的类型有效载荷,否则flow不知道可以从哪些结构进行细化,这可以在其他地方进行分解,但这也有助于锁定减速器中的变化,以防您不想处理的情况。
试流
type AppT = {}
type ActionT<T, P> = {|
type: T,
payload: P,
|};
type PayloadA = {| a: string |};
type PayloadB = {| b: string |};
const initialState = {};
const reducer = (
state: AppT = initialState,
action: ActionT<'ACTION_A', PayloadA> | ActionT<'ACTION_B', PayloadB>,
): AppT => {
switch (action.type) {
case 'ACTION_A': {
return {
...state,
a: action.payload.a,
};
}
case 'ACTION_B': {
return {
...state,
a: action.payload.a, // <-- it fails because type refines to PayloadB
b: action.payload.b,
};
}
default:
return state;
}
};