如何从包含多个类型的 Typescript 命名空间中获取联合类型?
我正在为我的 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 命名空间中所有类型和接口的联合类型?还是我应该将我的类型形状重新定义为其他形式?
答案#1
与其使用命名空间,也许你可以一开始就将其定义为联合类型。
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'>
