问题描述
我正在为redux
状态和相应操作定义类型。
这是我的组织方式:
declare namespace GLOBAL {
interface AUTH {
user: null | User
admin: boolean
}
interface APP_VERSION {
CURRENT: number
}
interface STATE {
AUTH: AUTH,APP_VERSION: APP_VERSOPM
}
declare namespace ACTIONS { // THESE ARE THE ACTIONS THAT UPDATE THE "GLOBAL" PART OF THE "Redux_STATE"
type UPDATE_AUTH = {
type: "UPDATE_AUTH",payload: AUTH
}
type UPDATE_APP_VERSION = {
type: "UPDATE_APP_VERSION",payload: APP_VERSION
}
// ETC
}
interface Redux_STATE { // THIS IS THE SHAPE OF THE TOP LEVEL Redux STATE
GLOBAL: GLOBAL.STATE,// "GLOBAL" USED WITHIN THE WHOLE APP
ADMIN: ADMIN.STATE // "ADMIN" IS ONLY USED IN ADMIN PAGES
}
}
现在我被困住了:我需要一种方式来引用所有更新GLOBAL
状态的动作。我将在globalStateReducer
中使用的某些方式,例如:
示例:
export const globalStateReducer(state: GLOBAL.STATE,actions: XXX) => {};
// NOTE: XXX should translate as the "UNION TYPE OF ALL ACTIONS LISTED IN GLOBAL.ACTIONS"
一种可能的解决方案:
每次我将动作添加到GLOBAL.ACTIONS
时,都可以将其手动添加到联合类型中,如下所示:
type ALL_GLOBAL_ACTIONS = UPDATE_AUTH | UPDATE_APP_VERSION | UPDATE_ANOTHER | UPDATE_SOMETHING | ETC...
然后我可以在我的globalStateReducer()
中引用它(它也会在其他地方使用):
export const globalStateReducer(state: GLOBAL.STATE,actions: GLOBAL.ALL_GLOBAL_ACTIONS) => {};
但这是重复的工作,容易出错。
是否有一种自动的方法来引用GLOBAL.ACTIONS
名称空间内存在的所有类型和接口的联合类型?还是应该将类型的形状重新定义为其他形状?
解决方法
您可以从一开始就将其定义为联合,而不是使用名称空间。
type ACTIONS =
| {
type: "UPDATE_AUTH",payload: AUTH
}
| {
type: "UPDATE_APP_VERSION",payload: APP_VERSION
}
// Now a helper to access an action type by string key
type ACTION<T,A = ACTIONS> = A extends { type: T } ? A : never
const updateAuth = (): ACTION<'UPDATE_AUTH'> => {
return ({ type: "UPDATE_AUTH",payload: ... })
}
因此,您可以使用ACTIONS.UPDATE_AUTH
ACTION<'UPDATE_AUTH'>