VUEX中,关于dispatch使用时对payload的类型进行限制的解决方法

89 阅读2分钟

有这么一个action,我想限制payload的类型为IGetPagePayload

const systemModule: Module<ISystemState, IRootState> = {
    namespaced: true,
    ......
    actions: {
        getPageListAction({ commit }, payload: IGetPagePayload) {
            console.log(payload);
        }
    }
};

以下是IGetPagePayload的类型定义

export interface IQueryInfo {
    offset: number;
    size: number;
}
export interface IGetPagePayload {
    pageUrl: string;
    queryInfo?: IQueryInfo;
}

现在我要在某个地方通过store.dispatch,调用上面的getPageListAction方法并期望dispatch中第二个对象参数payload的类型被限制为IGetPagePayload,所以编写如下代码。

store.dispatch("system/getPageListAction", {
    pageUrl: "/user/list",
    queryInfo: {
        offset: 0,
        size: 10
    }
});

但查看queryInfo的类型,发现并不是所期望的IQueryInfo,而是自推导的 {offset:number;size:number;} 类型,说明payload的类型并没有得到限制。

查看源码中dispatch方法的类型定义,发现它的类型是Dispatch(定义如下)

dispatch: Dispatch;

export interface Dispatch {
  (type: string, payload?: any, options?: DispatchOptions): Promise<any>;
  <P extends Payload>(payloadWithType: P, options?: DispatchOptions): Promise<any>;
}

可以看出dispatch方法有两种传递参数的方式,第一种分别接收

  1. type:string
  2. payload?:any
  3. options?:DispatchOptions

以上三个参数,其中payload类型为any,显然没有任何方法能在此处做类型限制,所以考虑第二种传参方式

  1. 接收一个泛型P继承自接口Payload

  2. payloadWithType: P

  3. options?: DispatchOptions

看一下Payload的接口定义

export interface Payload {
  type: string;
}

也就是说,第二种传参方式需要接收一个含有type属性的泛型,并且会把该泛型赋给第一个参数payloadWithType,不难看出此处便可以通过构造一个含有type,并且包含原所需数据类型的接口来实现我们对payload的类型限制。

因此,修改接口IGetPagePayload将type属性纳入其中,随后修改dispatch的调用方法以泛型方式传入该类型。

export interface IGetPagePayload {
    type: string;
    pageUrl: string;
    queryInfo?: IQueryInfo;
}

store.dispatch<IGetPagePayload>({
    type: "system/getPageListAction",
    pageUrl: "/user/list",
    queryInfo: {
        offset: 0,
        size: 10
    }
});

再次查看queryInfo的类型,可以看到此处已被限制为IQueryInfo | undefined的可选类型,至此,对dispatch中payload的类型限制问题解决。