我正在尝试构建一个将基于操作类型使用类型保护的reducer对象。我想要这样的东西:
const myReducers: ReducerMap<MyState, FirstAction | SecondAction> = {
[FIRST]: (s, a) => s // a should be automatically cast to FirstAction with type guards
[SECOND]: (s, a) => s // a should be automatically cast to FirstAction with type guards
}
const FIRST = 'FIRST';
const SECOND = 'SECOND';
interface FirstAction extends Action<typeof FIRST> {some: string}
interface SecondAction extends Action<typeof Second> {some: string}
有了开关盒,我可以使它工作,因为类型防护会过滤不同的type
类型。
function test(s: {}, a: LoadAction | DataAction) {
switch (a.type) {
case LOAD_EVENT:
return { ...s, id: a.id }; // auto cast to LoadAction
case LOAD_EVENT_SUCCESS:
return { ...s, ...a.data }; // auto cast to DataAction
}
return s;
}
但是在对象中我无法做到。
我尝试了以下操作,仅返回所有可能的操作:
type ActionFilter<A extends Action, T extends string> = {[P in T]: P extends A['type'] ? A : never}[T];
let x: ActionFilter<LoadAction | DataAction, typeof LOAD_EVENT>;
// expected x: LoadAction, but got x: LoadAction | DataAction
我也尝试了以下方法,但是无法编译
interface ReducerMap<S, A extends Action> {
[key: typeof A['type']]: (s: S, a: A) => S;
// 'A' only refers to a type, but is being used as a value here.
// An index signature parameter type must be 'string' or 'number'.
}
答案 0 :(得分:1)
找到了
type ActionFilter<A extends Action, T extends string> = {[P in T]: A extends Action<T> ? A : never}[T];
因此显然我无法与Action ['type']进行比较,因为此时的类型是任意类型,但是我可以检查我的动作是否扩展了正确的动作类型。