【问题标题】:Union type dispatch callback联合类型调度回调
【发布时间】:2021-11-19 03:19:52
【问题描述】:

我正在尝试创建一个通用函数,该函数将用于创建回调操作。 但我不确定在这种情况下如何处理联合类型。 该函数将收到type,如果需要,回调将收到payload。 如果需要有效负载,and 函数将返回带有字段 typepayload 的对象。

我声明的接口:

enum ActionTypes {
    CREATE_GAME = 'CREATE_GAME',
    GET_GAME_INFO = 'GET_GAME_INFO',
    PARTICIPANT_JOIN = 'PARTICIPANT_JOIN',
}

interface CreateGame {
    type: ActionTypes.CREATE_GAME;
}

interface GameInfoPayload {
    gameid: number,
    participants: [],
    phase: string,
    activated: boolean
}

interface GetGameInfo {
    type: ActionTypes.GET_GAME_INFO;
    payload: GameInfoPayload;
}

interface ParticipantJoin {
    type: ActionTypes.PARTICIPANT_JOIN;
    payload: boolean;
}

type GameAction = CreateGame |
                  GetGameInfo |
                  ParticipantJoin;

type PayloadGameAction = Extract<GameAction, {payload: unknown}>

我正在尝试创建的回调:

const buildAction = (action:ActionTypes) => {
    return (payload:PayloadGameAction['payload']):GameAction => {
        return {
            type: action,
            payload: payload
        }
    }
}

const createGame = buildAction(ActionTypes.CREATE_GAME);
const getGameInfo = buildAction(ActionTypes.GET_GAME_INFO);
const participantJoin = buildAction(ActionTypes.PARTICIPANT_JOIN);

最后产生的错误:

Type 'boolean | GameInfoPayload' is not assignable to type 'boolean'.
  Type 'GameInfoPayload' is not assignable to type 'boolean'.

很高兴得到任何帮助。

【问题讨论】:

  • 提醒一下:我们不再推荐使用“联合类型”样式,因为它是大量的额外代码,没有任何好处。 (请参阅phryneas.de/redux-typescript-no-discriminating-union)请改用官方的 Redux Toolkit,这是官方推荐编写 any Redux 代码已有两年多的时间了,它会为您处理几乎所有的 TypeScript 类型。
  • 好的,这就是我要找的

标签: typescript redux typescript-generics


【解决方案1】:

你可以试试generic types

enum ActionTypes {
    CREATE_GAME = 'CREATE_GAME',
    GET_GAME_INFO = 'GET_GAME_INFO',
    PARTICIPANT_JOIN = 'PARTICIPANT_JOIN',
}

interface GameInfoPayload {
    gameid: number,
    participants: [],
    phase: string,
    activated: boolean
}

interface CreateGame {
    type: ActionTypes.CREATE_GAME;
    // notice payload here
    payload: undefined
}

interface GetGameInfo {
    type: ActionTypes.GET_GAME_INFO;
    payload: GameInfoPayload;
}

interface ParticipantJoin {
    type: ActionTypes.PARTICIPANT_JOIN;
    payload: boolean;
}

type GameAction =
    | CreateGame
    | GetGameInfo
    | ParticipantJoin

type MathingGameActions<T extends ActionTypes> = Extract<GameAction, { type: T }>

const buildAction = <T extends ActionTypes = ActionTypes, K extends 
MathingGameActions<T> = MathingGameActions<T>>(action: T) =>
    (payload: K['payload']): K => {
        const result = {
            type: action
        }
        // prepare result here
        return result as unknown as K
    }

const createGame = buildAction(ActionTypes.CREATE_GAME)
const getGameInfo = buildAction(ActionTypes.GET_GAME_INFO)
const participantJoin = buildAction(ActionTypes.PARTICIPANT_JOIN)

其他选项是function overload, 也许this 会有所帮助

【讨论】:

  • 太好了,谢谢你的提示。我想知道不添加payload: undefinedCreateGame接口可以解决吗?
猜你喜欢
  • 1970-01-01
  • 2021-09-03
  • 1970-01-01
  • 1970-01-01
  • 2021-12-14
  • 1970-01-01
  • 2019-02-08
  • 1970-01-01
  • 2019-04-20
相关资源
最近更新 更多