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 匹配。
