如何获得另一个联盟的特定领域的联合

时间:2017-02-13 12:55:28

标签: javascript redux flowtype

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

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

type Actions = A | B

我希望有一个类型ActionType,它是我行动的所有可能type的联合。即:

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

换句话说,我想在联合(type)中得到字段(A | B)的所有可能值的并集。

流量是否可以实现?

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

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

然后我确信我只能使用有效的操作类型调用take

2 个答案:

答案 0 :(得分:0)

你可以这样建模:

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!

答案 1 :(得分:0)

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

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