网站搜索

reactjs - 在使用 TypeScript 的 Redux reducer 中,属性在类型上不存在?


我正在尝试在一个小的学习项目中将 Redux 与 TypeScript 一起使用,按照这个教程:https://redux.js.org/recipes/usage-with-typescript/

const INITIAL_STATE: TweetsState = {
  tweets: []
};

const tweetsReducer: Reducer<TweetsState> = (
  state = INITIAL_STATE,
  action: TweetAction
): TweetsState => {
  switch (action.type) {
    case GET_TWEETS:
      return {
        ...state
      };

    case TWEETS_RECEIVED:
      return {
        tweets: [...state.tweets, action.payload]
      };

    default:
      return state;
  }
};

我的 reducer 期望一个类型为 TweetAction 的动作,它是两个接口的联合:

export interface IGetTweetsAction {
  type: typeof GET_TWEETS;
}

export interface ITweetsReceivedAction {
  type: typeof TWEETS_RECEIVED;
  payload: ITweet[];
}

export const GET_TWEETS: string = "GET_TWEETS";
export const TWEETS_RECEIVED: string = "TWEETS_RECEIVED";

export type TweetAction = IGetTweetsAction | ITweetsReceivedAction;

然而,在我的 reducer 中,我收到错误 Property 'payload' does not exist on type 'TweetAction',这让人困惑,因为这似乎表明联合类型没有生效?

但这更令人困惑,因为在我的 actions 文件中,它明确允许我返回一个对象,类型为 TweetAction,并包含一个 payload:

import {
  TweetAction,
  GET_TWEETS,
  TWEETS_RECEIVED,
  ITweet
} from "./tweets.types";

export const getTweets = (): TweetAction => ({
  type: GET_TWEETS
});

export const tweetsReceived = (tweets: ITweet[]): TweetAction => ({
  type: TWEETS_RECEIVED,
  payload: tweets
});

我知道代码目前有点乱(作为一个 C# 开发者,我有时会本能地给接口加上 I 前缀,抱歉!),因为我还没有经历重构阶段,只是想快速弄出一些东西,但这个错误让我感到困惑。

有人能看出出了什么问题吗?可能只是一些简单的事情,但孤独感可能让我有些恍惚。

谢谢!

编辑:请注意,移除类型安全并将:action: TweetAction 改为仅使用 action 允许我使用 action.payload,功能仍然可以正常运行...

答案#1

-- 编辑 -----

好的,所以显然你需要在那些行中去掉 : string 类型声明:

export const GET_TWEETS: string = "GET_TWEETS";
export const TWEETS_RECEIVED: string = "TWEETS_RECEIVED";

-- /编辑 -----

我对 TypeScript 也相当陌生,但据我理解,因为你在 reducer 中使用了 action.payload,所以类型 TweetAction 不被接受,因为它可能意味着 IGetTweetsAction 类型,而该类型未定义 payload 属性。

你需要使用一个更通用的类型,比如:type TweetAction { type:/..., }

就是说你可以有一个动作,它将始终有一个 type,并且可能还有其他属性(例如 payload)。

至于你那个令人困惑的例子,我认为那实际上是有道理的:

export const getTweets = (): TweetAction => ({
  type: GET_TWEETS
});

没有定义 payload,所以它匹配 IGetTweetsAction。

export const tweetsReceived = (tweets: ITweet[]): TweetAction => ({
  type: TWEETS_RECEIVED,
  payload: tweets
});

而这个与 ITweetsReceivedAction 匹配。