如何从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名称空间内存在的所有类型和接口的联合类型?还是应该将类型的形状重新定义为其他形状?

解决方法

您可以从一开始就将其定义为联合,而不是使用名称空间。

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'>