首页 > 解决方案 > 使用 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;

但是,在我的减速器中,我得到了Property 'payload' does not exist on type 'TweetAction'令人困惑的错误,因为它表明联合没有工作?

但这更加令人困惑,因为在我的操作文件中,它清楚地允许我返回一个 TweetAction 类型的对象,并带有有效负载:

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# 开发人员,对不起!)因为我还没有经历过重构阶段,因为我只是想搞点事情很快,但我被这个错误难住了。

谁能看到出了什么问题?这可能是直截了当的事情,但孤立可能会影响我的头脑。

谢谢!

编辑:请注意,删除类型安全和更改: action: TweetActionaction允许我这样做action.payload并且功能工作正常......

标签: reactjstypescriptredux

解决方案


- 编辑 - - -

好的所以显然你需要删除: string这些行中的输入:

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

- /编辑 - - -

我对打字稿也很陌生,但据我了解,由于您action.payload在减速器中使用该类型,TweetAction因此不接受该类型,因为它可能暗示IGetTweetsAction未定义payload属性的类型。

您需要使用更通用的类型,例如: type TweetAction { type: // ..., }

说你可以有一个总是有 atype并且可能有一些其他道具(例如 a payload)的动作。

至于您令人困惑的示例,我认为这实际上是有道理的:

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

没有payload定义所以它匹配IGetTweetsAction

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

而这一个匹配ITweetsReceivedAction


推荐阅读