Redux FlowJs:如何键入谓词函数?

Redux FlowJs:如何键入谓词函数?,redux,flowtype,Redux,Flowtype,我正在尝试在我的应用程序中实现某种类型的通用redux reducer,它应该处理流类型的错误 假设我有FSA的Flowtype定义: type Action<P, M = void> = { type: string, payload: P, meta?: M, error?: boolean } 正如文档中提到的,这个函数的主体是一个简单的表达式 最后,我有一个简单的通用操作处理程序: function handle(a: Action<string |

我正在尝试在我的应用程序中实现某种类型的通用redux reducer,它应该处理流类型的错误

假设我有FSA的Flowtype定义:

type Action<P, M = void> = {
  type: string,
  payload: P,
  meta?: M,
  error?: boolean
}
正如文档中提到的,这个函数的主体是一个简单的表达式

最后,我有一个简单的通用操作处理程序:

function handle(a: Action<string | Error>) {
  if (isErrorAction(a)) {
    console.log(a.payload.message);
  }
}
当我在动作处理程序中内联谓词函数时,一切都正常。所以我可能遗漏了一些关于谓词函数的内容


[]

在您最初的示例中,我认为这是Flow谓词函数的一个缺陷,当主语是参数时,它似乎可以正常工作,但当它是参数的成员时就不行了

然而,似乎你想要一些语法糖,在这种情况下,拯救

注意:您必须在使用前测试
有效载荷
错误
是否存在(truthy),否则它将警告它可能正在处理其他类型,因此在访问
a.payload
之前会出现else条件

()

类型成功操作={|
有效载荷:P,
元?:M,
|}
类型FailureAction={|
错误:错误,
元?:M,
|}
类型动作=成功动作|失败动作
功能手柄1(a:动作){
如果(a.错误){
console.error(a.error.message);
}否则{
console.log(a.payload)
}
}
const success={payload:'yay'};
常量错误={error:newerror('bork')};
(成功:成功行动);//通过
(成功:失败行动);//失败:无法将'success'强制转换为'FailureAction',因为对象文字中缺少属性'error'
(错误:FailureAction);//通过
(错误:SuccessAction);//失败:无法将'error'强制转换为'SuccessAction',因为'SuccessAction'中缺少属性'error'`
constboth={payload:'yay',error:newerror('bork')};
(两者:行动);//Fail:(意译)缺少'error'或'payload'
const north={};
(都不是:行动);//Fail:(意译)不精确的文字与'SuccessAction'或'FailureAction'不兼容`

看起来flowtype无法从谓词函数中的对象优化属性:


就我个人而言,我已经结束了以下的

感谢您的解决方案,但我与flux标准操作有关,因此操作必须只有
有效负载
属性,
错误
属性是可选的,应该是布尔值。但我修改了你的方法:如果meta在成功和失败方面都是同一类型的,那么你不一定需要SM和EM。严格地说,根据flux文档,负载可以是可选的,但按照惯例是一个错误。如果将其设置为
有效载荷?
,则在访问
action.payload.message
之前需要进行额外检查,例如
如果(action.error&&action.payload)
同意,但我有意根据需要添加有效载荷以减少此谓词表达式。这是一种折衷办法,在有效负载为空的情况下,
P
可以声明为
void
function handle(a: Action<string | Error>) {
  if (isErrorAction(a)) {
    console.log(a.payload.message);
  }
}
console.log(a.payload.message);
                              ^ Cannot get `a.payload.message` because property `message` is missing in `String` [1].
type SuccessAction<P, M = void> = {|
  payload: P,
  meta?: M,
|}

type FailureAction<P, M = void> = {|
  error: Error,
  meta?: M,
|}

type Action<P, M = void> = SuccessAction<P, M> | FailureAction<P, M>

function handle1(a: Action<string>) {
  if (a.error) {
    console.error(a.error.message);
  } else {
    console.log(a.payload)
  }
}

const success = { payload: 'yay' };
const error = { error: new Error('bork') };
(success: SuccessAction<string>);   // Pass
(success: FailureAction<string>);   // Fail: Cannot cast `success` to `FailureAction` because property `error` is missing in object literal
(error: FailureAction<string>);     // Pass
(error: SuccessAction<string>);     // Fail: Cannot cast `error` to `SuccessAction` because property `error` is missing in `SuccessAction`

const both = { payload: 'yay', error: new Error('bork') }; 
(both: Action<string>);             // Fail: (paraphrased) either `error` or `payload` is missing

const neither = { }; 
(neither: Action<string>);          // Fail: (paraphrased) inexact literal not compatible with `SuccessAction` or `FailureAction`