如何使用Flow导出动作创建者返回值的类型?

Kyl*_*len 5 javascript reactjs flowtype redux flow-typed

我目前正在导出2个动作创建者:

export const login = (payload: $PropertyType<Actions.Login, 'payload'>): Actions.Login => ({
  type: LOGIN,
  payload,
})

export const logout = (payload: $PropertyType<Actions.Logout, 'payload'>): Actions.Logout => ({
  type: LOGOUT,
  payload,
})
Run Code Online (Sandbox Code Playgroud)

这些是它们各自的动作:

export type Login = {
  type: ActionType,
  payload: {
    username: string,
    password: string,
  },
}

export type Logout = {
  type: ActionType,
  payload: null,
}
Run Code Online (Sandbox Code Playgroud)

在另一个文件中,我使用通配符语法导入创建者

import * as Actions from ...
Run Code Online (Sandbox Code Playgroud)

然后,我试图从这些动作中提取其返回类型的形状,以用作我的减速器的动作类型。

我想要获得的是以下内容(我认为,这是Flow期望满足减速器要求的一种type特性):

type Action = { 
    login: { type: '', payload: '' }, 
    logout: { type: '', payload: '' } 
}
Run Code Online (Sandbox Code Playgroud)

我已经达到了这个功能:

type Action = $ObjMap<typeof Actions, <V>(V) => $Call<V>>
Run Code Online (Sandbox Code Playgroud)

返回以下内容:

Action: type Action = { 
    login: Login,
    logout: Logout
}
Run Code Online (Sandbox Code Playgroud)

确实是这些创作者返回的动作。但是,reducer中的Flow不会type在该操作中获取该属性。

减速器看起来像这样:

const reducer = (state: State = initialState, action: Action): State => {
  switch (action.type) {
    case LOGIN:
      return { ...state }
    default:
      return state
  }
}
Run Code Online (Sandbox Code Playgroud)

错误action.type是:

[flow] property `type` is missing in object type [1]. (References: [1])
Run Code Online (Sandbox Code Playgroud)

非常感谢您编写更好的通用函数的任何帮助。谢谢。

Fil*_*vić 0

首先,从包含操作创建者的模块导入模块导出的类型:

import typeof * as ActionCreators from './actions'
Run Code Online (Sandbox Code Playgroud)

这将是一个对象类型,因此$ObjMap实用程序帮助器可用于将每个操作创建者映射到其返回值的类型。这里需要注意的是:

  • 确保A从动作创建者返回的动作是准确的
  • 用于$Values获得所有确切操作类型的联合

以下应该产生一个类型,其中包含创建者返回的所有可能操作的并集,可以通过{ type }化简器中的属性轻松地对其进行细化:

type Action = $Values<$ObjMap<ActionCreators, <A>((...any[]) => A) => $Exact<A>>>
Run Code Online (Sandbox Code Playgroud)

您可以在Try Flow上查看此示例,了解其实际效果。请注意,对于loginlogout操作类型,将操作类型字符串指定为空的默认情况会引发尚未处理的;(action.type: empty)错误。action.type === 'login'action.type === 'logout'