在Redux、Immutable.js和TypeScript中使用useSelector时避免类型Assert

dgsult0t  于 2023-06-30  发布在  TypeScript
关注(0)|答案(1)|浏览(122)

我目前正在使用Redux,Immutable.js和TypeScript的组合。我在从useSelector钩子中获取正确的类型时遇到了麻烦,于是我求助于使用类型Assert。我知道这并不理想,我正在寻找一个更好的方法来处理这种情况。
下面是我的代码示例:

const selectedConInfo = useSelector(
    (state: RootState) => state.conversations.toJS().selectedConInfo,
  ) as Conversation;
  const emailsState = useSelector((state: RootState) =>
    state.emails.get('emails').toJS(),
  );
  const currentEmails = emailsState[selectedConInfo.id] as Email[];

我想避免在这段代码中使用类型Assert(如Conversation和Email[])。但是,没有它们我就找不到合适的类型。
下面是相关代码:

export const rootReducer = combineReducers({
  emails: emailsReducer,
});

export type RootState = ReturnType<typeof rootReducer>;

---
const initialState = {
  loading: false,
  emails: Map<string, List<Email>>({}),
  error: null,
};

const emailsReducer = (state = Map(initialState), action: EmailAction) => {
  switch (action.type) {
    case EMAILS_FETCH_REQUEST:
      return state.set('loading', true).set('error', null);
    case EMAILS_FETCH_SUCCESS:
      return state
        .set('loading', false)
        .setIn(['emails', action.meta], List(action.payload.data));

...
---

function EmailArea() {
  const dispatch = useDispatch();
  const selectedConInfo = useSelector(
    (state: RootState) => state.conversations.toJS().selectedConInfo,
  ) as Conversation;
  const emailsState = useSelector((state: RootState) =>
    state.emails.get('emails').toJS(),
  );
  const currentEmails = emailsState[selectedConInfo.id] as Email[];

我将非常感谢任何关于如何在这种情况下改进类型推理的建议。谢谢你!
快乐编码!

gcmastyq

gcmastyq1#

我也有同样的挣扎。如果设置了类型,我建议使用Record而不是Map。此外,你可以使用Immutable.js的List和Map,类似于JavaScript的Array和Map。因此,通过将Map更改为Record并删除toJS,您应该获得预期的类型并能够将其与TypeScript一起使用。下面的代码片段演示了我将如何实现这些更改:

const initialState: EmailState = {
  loading: false,
  emails: Map<string, Record<EmailInfo>>(),
  error: null,
};

...

function EmailArea() {
  const dispatch = useDispatch();
  const selectedConInfo = useSelector(
    (state: RootState) => state.conversations.selectedConInfo,
  );
  const emailsState = useSelector((state: RootState) =>
    state.emails.get('emails'),
  );

我希望这个修改后的解释更流畅、更清晰。

相关问题