在React中使用Enum类型和不同的载荷类型编写useReducer的示例:

huangapple go评论110阅读模式
英文:

Typing useReducer in React with Enum type with different payload types

问题

我正在编写一个接受带有 Enum 类型 type 属性的 action 的 reducer 函数,而 action 的 payload 取决于 Enum 类型。

我知道可以使用联合类型为每个枚举类型提供不同的 payload 类型,但我有一个 action,它的 payload 类型是 Date,而所有其他 action 的 payload 类型都是 number。

我尝试过的

enum DatePickerActionType {
    PICK_YEAR = 'PICK_YEAR',
    PICK_MONTH = 'PICK_MONTH',
    PICK_DATE = 'PICK_DATE',
    PICK_HOURS = 'PICK_HOURS',
    PICK_MINUTES = 'PICK_MINUTES',
}

type DatePickerAction =
    | {
          type: DatePickerActionType.PICK_DATE;
          payload: Date;
      }
    | {
          type: DatePickerActionType;
          payload: number;
      };

const datePickerReducer = (state: DatePickerValue, action: DatePickerAction): DatePickerValue => {
    switch (action.type) {
        case DatePickerActionType.PICK_DATE: {
            const a = action.payload;
        }
        //...
    }
};

然而,当 action 类型为 PICK_DATE 时, TypeScript 仍然显示 action.type 为 number 或 Date
在React中使用Enum类型和不同的载荷类型编写useReducer的示例:

是否有方法可以为除了枚举类型以外的所有 action 定义 payload 类型为 number,还是我应该使用联合类型分别定义所有 action?

type DatePickerAction =
    | {
          type: DatePickerActionType.PICK_DATE;
          payload: Date;
      }
    | {
          type: DatePickerActionType.PICK_HOURS;
          payload: number;
      }
    | {
          type: DatePickerActionType.PICK_MINUTES;
          payload: number;
      }
    | {
          /**... */
      };

(注意:代码部分没有翻译,只提供翻译好的文本。)

英文:

I am writing reducer function which accepts action with type property whos type is Enum type and action payload depends on Enum type.

I know that I can provide different payload types for each enum type using union types, but I have one action which payload is Date and all other actions have payload type of number.

What I've tried

enum DatePickerActionType {
    PICK_YEAR = 'PICK_YEAR',
    PICK_MONTH = 'PICK_MONTH',
    PICK_DATE = 'PICK_DATE',
    PICK_HOURS = 'PICK_HOURS',
    PICK_MINUTES = 'PICK_MINUTES',
}

type DatePickerAction =
    | {
          type: DatePickerActionType.PICK_DATE;
          payload: Date;
      }
    | {
          type: DatePickerActionType;
          payload: number;
      };

const datePickerReducer = (state: DatePickerValue, action: DatePickerAction): DatePickerValue => {
    switch (action.type) {
        case DatePickerActionType.PICK_DATE: {
            const a = action.payload;
        }
        //...
    }
};

However typescript still shows me action.type as number or Date when action type is PICK_DATE
在React中使用Enum类型和不同的载荷类型编写useReducer的示例:

Is there way to define payload type as number for all actions except on enum type or I should go with union type defining all actions separately?

type DatePickerAction =
    | {
          type: DatePickerActionType.PICK_DATE;
          payload: Date;
      }
    | {
          type: DatePickerActionType.PICK_HOURS;
          payload: number;
      }
    | {
          type: DatePickerActionType.PICK_MINUTES;
          payload: number;
      }
    | {
          /**... */
      };

答案1

得分: 1

尝试使用Exclude来排除特定的枚举:

// ...

type DatePickerAction =
    | {
        type: DatePickerActionType.PICK_DATE;
        payload: Date;
    }
    | {
        type: Exclude<DatePickerActionType, DatePickerActionType.PICK_DATE>;
        payload: number;
    };


const datePickerReducer = (state: DatePickerValue, action: DatePickerAction): DatePickerValue => {
    switch (action.type) {
        case DatePickerActionType.PICK_DATE: {
            const a = action.payload; // 日期(Date)
            break;
        }
        default: {
            const a = action.payload; // 数字(number)
        }
        //...
    }
};

TS Playground

英文:

Try Exclude the specific enum:

// ...

type DatePickerAction =
    | {
        type: DatePickerActionType.PICK_DATE;
        payload: Date;
    }
    | {
        type: Exclude&lt;DatePickerActionType, DatePickerActionType.PICK_DATE&gt;;
        payload: number;
    };


const datePickerReducer = (state: DatePickerValue, action: DatePickerAction): DatePickerValue =&gt; {
    switch (action.type) {
        case DatePickerActionType.PICK_DATE: {
            const a = action.payload; // Date
            break;
        }
        default: {
            const a = action.payload; // number
        }
        //...
    }
};

TS Playground

huangapple
  • 本文由 发表于 2023年6月5日 15:40:17
  • 转载请务必保留本文链接:https://go.coder-hub.com/76404386.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定