使用区分联合类型和反应减速器

问题描述 投票:0回答:1

努力理解如何将可区分的联合类型与减速器一起使用。下面是我的减速器的设置方式。我希望能够将其传递到提供程序组件中,但不断遇到类型错误。

export const enum LoadingState {
  idle = "idle",
  loading = "loading",
  loaded = "loaded",
  error = "error",
}

export type SampleState =
  | {
      status: LoadingState.idle;
    }
  | {
      status: LoadingState.loading;
    }
  | {
      status: LoadingState.loaded;
      sampleDetails: SampleDetails;
    }
  | {
      status: LoadingState.error;
      error: any;
    };

export const INITIAL_STATE: SampleState = {
  status: LoadingState.idle,
};

export type Action =
  | {
      type: "SET_SAMPLE_LOADING_STATE";
      payload: { status: LoadingState };
    }
  | {
      type: "SET_SAMPLE";
      payload: { sampleDetails: SampleDetails };
    };

export const reducer = (state: SampleState, action: Action) => {
  switch (action.type) {
    case "SET_SAMPLE_LOADING_STATE":
      return {
        ...state,
        status: action.payload.status,
      };

    case "SET_SAMPLE":
      return {
        ...state,
        status: LoadingState.loaded,
        sampleDetails: action.payload.sampleDetails,
      };

    default:
      return state;
  }
};


// Trying to use it here in a provider
const [state, dispatch] = useReducer(
  reducer,
  INITIAL_STATE
);

但我不断得到:

   Argument of type 'SampleState' is not assignable to parameter of type 'never'.
  Type '{ status: LoadingState.idle; }' is not assignable to type 'never

我这里的设置有问题吗?如果我从联合中删除其他类型,它会按预期工作。

reactjs typescript react-hooks union-types
1个回答
0
投票

由于您要将前一个状态与下一个状态合并,因此如果前一个状态为“错误”,并且您使用

"SET_SAMPLE_LOADING_STATE"
操作将其设置为“空闲”,则最终可能会出现无效状态,例如:

{
  status: LoadingState.idle,
  error: 'something'
}

我认为你可以通过显式地使

reducer
返回
SampleState
来解决这个问题,并让它对你正在设置的状态进行更细粒度的检查,例如:

if (action.payload.status === LoadingState.loaded) {
  return {
    status: LoadingState.idle,
  }
} else if ...
© www.soinside.com 2019 - 2024. All rights reserved.