使用typescript删除异步api调用类型中的重复项

时间:2019-01-09 13:37:37

标签: typescript

我具有以下类型的并集:

export interface GetAll { type: PeopleActionTypes.GET_ALL; }
export type GetAllOk = ApiActionCreator<{ type: PeopleActionTypes.GET_ALL_OK; }>;
export type GetAllFail = ApiActionCreator<{type: PeopleActionTypes.GET_ALL_FAIL}>;
export type GetOne = ApiActionCreator<{type: PeopleActionTypes.GET_ONE}>;
export type GetOneOk = ApiActionCreator<{type: PeopleActionTypes.GET_ONE_OK}>;
export type GetOneFail = ApiActionCreator<{type: PeopleActionTypes.GET_ONE_FAIL}>;
export type Add = ApiActionCreator<{type: PeopleActionTypes.ADD}, Fetchable<Person>>;
export type AddOK = ApiActionCreator<{type: PeopleActionTypes.ADD_OK}, Fetchable<Person>[]>;
export type AddFail = ApiActionCreator<{type: PeopleActionTypes.ADD_FAIL}>;
export type Update = ApiActionCreator<{type: PeopleActionTypes.UPDATE}>;
export type UpdateOK = ApiActionCreator<{type: PeopleActionTypes.UPDATE_OK}, Fetchable<Person>[]>;
export type UpdateFail = ApiActionCreator<{type: PeopleActionTypes.UPDATE_FAIL}>;
export type Remove = ApiActionCreator<{type: PeopleActionTypes.REMOVE}>;
export type RemoveOK = ApiActionCreator<{type: PeopleActionTypes.REMOVE_OK}>;
export type RemoveFail = ApiActionCreator<{type: PeopleActionTypes.REMOVE_FAIL}>;
export type ResetPassword = ApiActionCreator<{type: PeopleActionTypes.RESET_PASSWORD}>;
export type ResetPasswordOK = ApiActionCreator<{type: PeopleActionTypes.RESET_PASSWORD_OK}>;
export type ResetPasswordFail = ApiActionCreator<{type: PeopleActionTypes.RESET_PASSWORD_FAIL}>;

export interface SetCurrent {
  type: PeopleActionTypes.SET_CURRENT;
  id: string;
};

export type PeopleActionCreators =
    SetCurrent
    | GetAll
    | GetAllOk
    | GetAllFail
    | GetOne
    | GetOneOk
    | GetOneFail
    | Add
    | AddOK
    | AddFail
    | Update
    | UpdateOK
    | UpdateFail
    | Remove
    | RemoveOK
    | RemoveFail
    | ResetPassword
    | ResetPasswordOK
    | ResetPasswordFail;

我的ApiActionCreator如下所示:

export type ApiActionCreator<T extends object, Payload = object | any[] | undefined> = T & { payload: Payload, error: ErrorMessage }

对于每个操作,我都有一个XxxXxxOK和一个XxxFail

无论如何,打字稿中是否仍可以某种方式生成这些类型,而不必为所有操作创建全部3种?

1 个答案:

答案 0 :(得分:1)

您可以避免通过使用有条件的,有条件的类型(包含在包含联合的类型参数上)来声明所有联合。使用这种行为,我们可以将ApiActionCreator应用于枚举文字联合的所有成员。

我们可以使用PeopleActionTypes条件类型(SET_CURRENT)来获取Exclude中不包括type PeopleActionTypesKeys = Exclude<PeopleActionTypes, PeopleActionTypes.SET_CURRENT>的所有文字枚举的并集,以不同的方式对其进行处理

唯一存在的问题是某些操作类型的自定义有效负载。我们可以将对象类型用作映射,以保持枚举成员与有效负载类型之间的关系。

type GetPayload<TPayloadMap, T extends PropertyKey> = TPayloadMap extends Record<T, infer U> ? U : undefined;

export type StandardActions<TEnumKeys, TPayloadMap> =
    TEnumKeys extends any  ? ApiActionCreator<{type: TEnumKeys }, GetPayload<TPayloadMap, TEnumKeys>> 
    : never ;


export interface SetCurrent {
    type: PeopleActionTypes.SET_CURRENT;
    id: string;
};

type PeopleActionTypesKeys = Exclude<PeopleActionTypes, PeopleActionTypes.SET_CURRENT>

export type PeopleActionCreators = SetCurrent | StandardActions<PeopleActionTypesKeys, {
    [PeopleActionTypes.ADD]: Fetchable<Person>,
    [PeopleActionTypes.UPDATE]: Fetchable<Person>,
    [PeopleActionTypes.ADD_OK]: Fetchable<Person>,
}>;

上述解决方案的重复次数较少,不幸的是,如果将鼠标悬停在PeopleActionCreators上,则会丢失类型别名的漂亮名称。

type PeopleActionCreators = SetCurrent | ApiActionCreator<{
    type: PeopleActionTypes.GET_ALL;
}, undefined> | ApiActionCreator<{
    type: PeopleActionTypes.GET_ALL_OK;
}, undefined> | ApiActionCreator<{
    type: PeopleActionTypes.GET_ALL_FAIL;
}, undefined> | ApiActionCreator<{
    type: PeopleActionTypes.GET_ONE;
}, undefined> | ApiActionCreator<{
    type: PeopleActionTypes.GET_ONE_OK;
}, undefined> | ApiActionCreator<{
    type: PeopleActionTypes.GET_ONE_FAIL;
}, undefined> | ApiActionCreator<{
    type: PeopleActionTypes.ADD;
}, Fetchable<Person>> | ApiActionCreator<{
    type: PeopleActionTypes.ADD_OK;
}, Fetchable<Person>> | ApiActionCreator<{
    type: PeopleActionTypes.ADD_FAIL;
}, undefined> | ApiActionCreator<{
    type: PeopleActionTypes.UPDATE;
}, Fetchable<Person>> | ApiActionCreator<{
    type: PeopleActionTypes.UPDATE_OK;
}, undefined> | ApiActionCreator<{
    type: PeopleActionTypes.UPDATE_FAIL;
}, undefined> | ApiActionCreator<{
    type: PeopleActionTypes.REMOVE;
}, undefined> | ApiActionCreator<{
    type: PeopleActionTypes.REMOVE_OK;
}, undefined> | ApiActionCreator<{
    type: PeopleActionTypes.REMOVE_FAIL;
}, undefined> | ApiActionCreator<{
    type: PeopleActionTypes.RESET_PASSWORD;
}, undefined> | ApiActionCreator<{
    type: PeopleActionTypes.RESET_PASSWORD_OK;
}, undefined> | ApiActionCreator<{
    type: PeopleActionTypes.RESET_PASSWORD_FAIL;
}, undefined>

尽管可读性很差,但是可读性却很差,对于其他人来说,代码本身也可能更难以理解。