Redux操作的打字稿

时间:2018-10-29 18:55:11

标签: typescript

我正在尝试构建一个将基于操作类型使用类型保护的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'.
}

1 个答案:

答案 0 :(得分:1)

找到了

type ActionFilter<A extends Action, T extends string> = {[P in T]: A extends Action<T> ? A : never}[T];

因此显然我无法与Action ['type']进行比较,因为此时的类型是任意类型,但是我可以检查我的动作是否扩展了正确的动作类型。