网站搜索

如何从包含多个类型的 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'>