Typescript Redux -使用CreateSlice键入初始状态

unhi4e5o  于 2022-11-12  发布在  TypeScript
关注(0)|答案(2)|浏览(168)

我已经使用CreateSlice创建了我的减速器/动作,如下面的代码所示:

import { createSlice, PayloadAction } from '@reduxjs/toolkit';
import { Modal } from 'antd';

export interface ModalState {
  modalProps: React.ComponentProps<typeof Modal>;
  visible: boolean;
  modalContent: string;
}

export interface ModalInfos {
  modalProps: React.ComponentProps<typeof Modal>;
  modalContent: string;
}

const initialState = {
  modalProps: {},
  visible: false,
  modalContent: '',
};

const modal = createSlice({
  name: 'modal',
  initialState,
  reducers: {
    openModal(state, action: PayloadAction<ModalInfos>) {
      state.modalProps = action.payload.modalProps;
      state.modalContent = action.payload.modalContent;
      state.visible = true;
    },
    closeModal(state) {
      state.visible = false;
    },
  },
});

export const { openModal, closeModal } = modal.actions;

export default modal.reducer;

我没有输入我的initialstate(所以我没有使用我的ModalState接口),但是当我尝试这样做时:

const initialState: ModalState = {
  modalProps: {},
  visible: false,
  modalContent: '',
};

然后,我在下面的行中收到一条奇怪的错误消息:

state.modalProps = action.payload.modalProps;

消息是:

Type 'PropsWithChildren<ModalProps>' is not assignable to type 'WritableDraft<PropsWithChildren<ModalProps>>'.
  Types of property 'okButtonProps' are incompatible.
    Type 'Partial<{ href: string; target?: string | undefined; onClick?: ((event: MouseEvent<HTMLElement, MouseEvent>) => void) | undefined; } & BaseButtonProps & Pick<...> & { ...; } & Pick<...>> | undefined' is not assignable to type 'WritableDraft<Partial<{ href: string; target?: string | undefined; onClick?: ((event: MouseEvent<HTMLElement, MouseEvent>) => void) | undefined; } & BaseButtonProps & Pick<...> & { ...; } & Pick<...>>> | undefined'.
      Type 'Partial<{ href: string; target?: string | undefined; onClick?: ((event: MouseEvent<HTMLElement, MouseEvent>) => void) | undefined; } & BaseButtonProps & Pick<...> & { ...; } & Pick<...>>' is not assignable to type 'WritableDraft<Partial<{ href: string; target?: string | undefined; onClick?: ((event: MouseEvent<HTMLElement, MouseEvent>) => void) | undefined; } & BaseButtonProps & Pick<...> & { ...; } & Pick<...>>>'.
        Types of property 'defaultValue' are incompatible.
          Type 'string | number | readonly string[] | undefined' is not assignable to type 'string | number | string[] | undefined'.
            Type 'readonly string[]' is not assignable to type 'string | number | string[] | undefined'.
              The type 'readonly string[]' is 'readonly' and cannot be assigned to the mutable type 'string[]'.ts(2322)

不给我的initalState分配类型可以吗?如果不可以,“state.modalProps”和“action.payload.modalProps”的类型在我看来是相同的,所以我不知道如何修复这个问题。

lbsnaicq

lbsnaicq1#

不,你 * 必须 * 为你的initialState声明一个类型。这就是createSlice为其余的约简器解释state的实际类型的方式。你需要:

const initialState : ModalState = {
  modalProps: {},
  visible: false,
  modalContent: '',
};

在这里定义两个不同的接口并没有什么错。也就是说,如果你 * 真的 * 想避免定义两个公共字段两次,你可以这样做:

export interface ModalInfos {
  modalProps: React.ComponentProps<typeof Modal>;
  modalContent: string;
}
export interface ModalState extends ModalInfos {
  visible: boolean;
}

或:

export interface ModalState {
  modalProps: React.ComponentProps<typeof Modal>;
  visible: boolean;
  modalContent: string;
}

export type ModalInfos = Omit<ModalState, 'visible'>;
fdx2calv

fdx2calv2#

我找到的部分更新模态属性的解决方案:

// replace
// state.modalProps = action.payload.modalProps;
// with
state.modalProps = Object.assign(Object.assign({}, state.modalProps), action.payload.modalProps);

import { ModalProps } from 'antd/lib/modal';
import { CaseReducer, createSlice, PayloadAction } from '@reduxjs/toolkit';

type State = ModalProps;

const initialState: State = {
  visible: false
}

const reducers: {
  updateModal: CaseReducer<State, PayloadAction<ModalProps>
} = {
  updateModal(state, action) {
    return Object.assign(Object.assign({}, state), action.payload);
  }
};

const slice = createSlice({
  name: 'modal',
  initialState,
  reducers
});

export { updateModal } = slice.actions;

// in some React component
dispatch(updateModal({ onOk: () => { /* do something */ } }));

相关问题