【问题标题】:Conditional typing for redux reducerredux reducer 的条件类型
【发布时间】:2021-04-01 23:54:27
【问题描述】:

我正在尝试创建一个可重用的组件来呈现“选择”表单项及其相关选项。它接受 redux 属性,该属性是一个动作创建者,负责将所选选项传递到 redux 存储区以在整个应用程序中使用。

我有两个可以选择的动作创建者:

第一个是:

setCompany: (state, action: PayloadAction<string>) => {
        state.selectedCompany = action.payload;
    },

第二个是:

setStatus: (state, action: PayloadAction<SelectStatus['status']>) => {
        state.status = action.payload;
    },

JobState['status'] 类型为: status: 'success' | 'error' | 'default' | 'processing' | 'warning';

在 Select 组件中,我尝试执行以下操作:

interface SelectsProps {
fetchOptionData?: () => void;
optionsArray?: [];
placeholder: string;
showSearch: boolean;
badges: boolean;
redux?: ActionCreatorWithPayload<string | SelectStatus['status']>;
// I also tried ActionCreatorWithPayload<string> |                           //ActionCreatorWithPayload<SelectStatus['status']> but neither is working
}

在我的父组件中,我尝试传入上面定义的 setStatus 的 redux 操作。但是,我收到以下错误:

`Type 'ActionCreatorWithPayload<"success" | "error" | "default" | "processing" | "warning", string>' is not assignable to type 'ActionCreatorWithPayload<string, string>'.`

   <Selects
                        redux={setStatus}
                        placeholder='Default'
                        showSearch={false}
                        badges={true}
                        optionsArray={badges}
                    />
    };

如果我以联合身份执行此操作,它似乎默认为字符串,并且如果有效则不接受要传递的状态。有什么方法可以让我选择正确的有效负载类型?

谢谢

【问题讨论】:

  • 为什么是SelectStatus['status'] 而不是JobState['status']?他们是一样的吗?我认为您需要两个动作创建者的联合,而不是联合的动作创建者。试试redux?: ActionCreatorWithPayload&lt;string&gt; | ActionCreatorWithPayload&lt;JobState['status']&gt;
  • 哎呀你完全正确- SelectStatus 和 JobStatus 是相同的。我也尝试联合这两个动作创建者,但在执行以下操作时仍然收到错误:@LindaPaiste const onSelect = (value: string | SelectStatus['status']) =&gt; { setSelectedOption(value); if (redux) dispatch(redux(value)); }; 错误是:Argument of type 'string' is not assignable to parameter of type '"success" | "error" | "default" | "processing" | "warning"。嗯嗯嗯
  • 好吧,这是意料之中的,因为您可能有 setStatus,它只接受 Status,因此您不能使用可能是 stringStatus 的参数调用它。我需要查看更多代码才能找到解决方案。如果您的底层Select 只能处理string(例如e.target.value 始终只是string),您可能需要使用as 断言类型。
  • 可能Selects 需要是一个通用组件,其中选项值和动作创建者使用相同的类型T
  • 是的,我认为你是完全正确的 - 我将尝试将其重构为通用组件,而不是像我现在拥有的那样凌乱的方式。感谢您的帮助。联合更改确实解决了一些问题,并且断言类型帮助我解决了另一个问题。我觉得好像代码很混乱,以至于我不确定自己在做什么:D

标签: javascript reactjs typescript redux types


【解决方案1】:

解决方案

您需要两个动作创建者类型的联合,而不是联合的动作创建者。

redux?: ActionCreatorWithPayload<string> | ActionCreatorWithPayload<SelectStatus["status"]>;

说明

ActionCreatorWithPayload&lt;string | SelectStatus['status']&gt; 表示可以使用stringSelectStatus['status'] 的参数调用的动作创建者。 setCompany 可以,因为 SelectStatus['status']string 的子集。但是setStatus 是一个错误,因为它只能接受SelectStatus['status']。它不能接受联合。

您需要两个动作创建者的联合,即ActionCreatorWithPayload&lt;string&gt; | ActionCreatorWithPayload&lt;SelectStatus["status"]&gt;。这意味着您可以拥有一个接受string 的函数或一个接受SelectStatus['status'] 的函数。它不再需要接受两者的联合。

调用此联合时可能会遇到问题,因为您不知道它接受哪种参数类型。


注意:我不知道你为什么在一个地方使用SelectStatus["status"] 而在另一个地方使用JobState["status"]。我假设它们是相同的。我会将该类型提取为命名类型:

export type JobStatus = JobState["status"]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-06-05
    • 1970-01-01
    • 2022-07-31
    • 1970-01-01
    • 2017-10-18
    • 2021-04-27
    • 2020-04-13
    • 2020-06-28
    相关资源
    最近更新 更多