【问题标题】:How to get the union of the specific fields of another union如何获取另一个联合的特定字段的联合
【发布时间】:2017-02-14 20:57:39
【问题描述】:

我试图在我的 Redux 应用程序上尽可能多地保证类型安全,但我遇到了这个问题。基本上我有这些类型:

type ActionA = { type: 'A' }
type ActionB = { type: 'B' }

type Actions = A | B

我想要一个类型ActionType,它是我所有可能的行为types 的联合。即:

type ActionType = 'A' | 'B' // <-- How to get this from `Actions` ?

换句话说,我想在一个联合 (A | B) 中获取一个字段 (type) 的所有可能值的联合。

这甚至可以通过流量实现吗?

用例是当我需要直接编写动作类型时能够避免拼写错误的动作类型。例如,使用redux-saga,我可以编写take 的定义(示例过于简化):

define function take(action: ActionType, saga: Function)

那么我肯定只能用有效的操作类型调用take

【问题讨论】:

  • 我认为不可能完全按照您的要求进行。但是,我发布了几个答案,我认为这可能会满足您更广泛的要求。

标签: javascript redux flowtype


【解决方案1】:

你可以这样建模:

type ActionType = 'A' | 'B'
type Action = { type: ActionType }

type ActionA = { type: 'A' } & Action
type ActionB = { type: 'B' } & Action

文字有些重复,但我认为这是不可避免的。此外,使用这种结构,您不会出错,因为每个操作都被限制为只有一种有效类型。

像这样声明一个未知类型的动作本身并不是错误:

type ActionC = { type: 'C' } & Action

但它是一种不适合居住的类型,因为'C' 不是有效的ActionType,所以当你尝试使用它时会出现编译错误:

let c: ActionC = { type: 'C' }; // ERROR!

【讨论】:

  • 实际上这不起作用,因为在使用此方法(即:github.com/reactjs/redux/issues/290#issue-95943173)进行切换案例时,流程无法正确过滤可能的操作类型。我想这是因为“类型”是所有类型的联合,所以它不能正确地将动作形状与其类型名称匹配。我找不到一种方法让它与泛型一起工作:(
【解决方案2】:

另一种解决方案使用泛型:

type ActionType = 'A' | 'B'

type Action<T: ActionType> = { type: T }

// actually you may not want to bother defining these aliases
type ActionA = Action<'A'>
type ActionB = Action<'B'>

如果你想抽象出type的不同值,那么使用*

function doAction(action: Action<*>){
    ....
}

注意,*any 不同,并且(与 any 不同)Flow 将能够推断其值,因此您可以执行以下操作:

function getType(action: Action<*>): * {
    return action.type
}

let type1:'B' = getType({type: 'B'});   // OK
let type2:'A' = getType({type: 'B'});   // ERROR

【讨论】:

  • 感谢您的建议!我有这个想法,但我希望可以避免重复文字
  • 大多数不复制文字的原因并不真正适用于 Flow。当可以进行类型检查时,它们与枚举有很大不同。
  • 是的,如果它与我想要获得的所有点相匹配,我不介意复制。基本上我想要:1)在减速器中过滤动作形状(github.com/reactjs/redux/issues/290#issue-95943173)2)验证字符串文字。第一个适用于我目前的方法,但第二个很难在每个地方获得。它目前在创建新操作时有效,但不能阻止我写 takeAction('WRONG_ACTION')。理想情况下,我想赶上if (type === 'WRONG_ACTION'),但这似乎在今天看来不可能。
猜你喜欢
  • 1970-01-01
  • 2021-10-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-02-24
  • 2021-09-07
相关资源
最近更新 更多