我正试图在我的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
。
答案 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