首页 > 解决方案 > 联合类型上不存在属性

问题描述

我对联合类型有疑问:

首先,我定义了两个接口:

export interface Action {
  type: string;

export interface ActionWithPayload<T> extends Action {
  payload: T;
}

接下来,我定义了几个类型和一个联合类型以供以后使用:

export type LoadDrafts = Action;
export type LoadDraftsSuccess = ActionWithPayload<{ [K: string]: Draft }>;

export type DraftsActionsUnion =
  | LoadDrafts
  | LoadDraftsSuccess;

最后,我在 reducer 函数中使用 union 类型:

export const draftsReducer = (
  state = initialState,
  action: DraftsActionsUnion
): DraftsState => {
  switch (action.type) {
    case DraftsActionsTypes.LoadDrafts: {
      return {
        ...state,
        loading: true
      };
    }
    case DraftsActionsTypes.LoadDraftsSuccess: {
      return {
        ...state,
        loading: false,
        loaded: true,
        entities: {
          ...state.entities,
          ...action.payload
        }
      };
    }
    default: {
      return state;
    }
  }
};

还有我的问题 - 编译器编译该属性payload在我的联合类型上不存在(...action.payload导致此问题):

[ts]
Property 'payload' does not exist on type 'DraftsActionsUnion'.
  Property 'payload' does not exist on type 'Action'.

不知道这是一个错误还是我做错了什么。

标签: typescript

解决方案


我认为您在 2 种操作类型中缺少类型鉴别器字段的字符串文字值。您需要此开关来区分 case 块中实际存在的类型。有不止一种方法可以做到这一点,但这里有一种方法可以做到。

export interface Action<K extends string> {
  type: K;
}

export interface ActionWithPayload<K, T> extends Action<K> {
  payload: T;
}

export type LoadDrafts = Action<‘loadDrafts’&gt;;
export type LoadDraftsSuccess = ActionWithPayload<‘loadDraftSuccess’, { [K: string]: Draft }>;

这使您的类型列成为可以在继承接口时指定的通用字符串文字。

重要的是您的类型值是字符串文字而不是字符串,因此您可以获得一组有限的值,而不是有效地无限的字符串可能性。


推荐阅读