【发布时间】:2021-03-17 05:47:56
【问题描述】:
我正在尝试将 Typescript 与 Redux 一起使用,并根据 Redux Ducks 进行设计。我在这里与这种类型检查作斗争,我不知道为什么。
const UPDATE = "ticTacToe/board/update";
const RESET = "ticTacToe/board/reset";
export default function reducer(
state = initialState,
action: IBoardActions
): IBoardState {
switch (action.type) {
case UPDATE:
const { nextPlayer, clickedIndex } = action;
// TypeScript error: Property 'nextPlayer' does not exist on type
//'{ type: string; nextPlayer: string; clickedIndex: number; } | { type: string; }'. TS2339
const newSquares = [...state.squares];
newSquares[clickedIndex] = nextPlayer;
return {
squares: newSquares,
oIsNext: !state.oIsNext
};
case RESET:
return initialState
default:
return state;
}
}
type BoardAction = typeof updateBoard | typeof resetBoard;
export type IBoardActions = ReturnType<BoardAction>;
export function updateBoard(nextPlayer: string, clickedIndex: number) {
return {
type: UPDATE,
nextPlayer,
clickedIndex
};
}
export function resetBoard() {
return {
type: RESET
};
}
我尝试使用enum 修复它,但这也不起作用。是switch的问题吗?
enum Action {
UPDATE = 'update',
RESET = 'reset'
}
export default function reducer(
state = initialState,
action: IBoardActions
): IBoardState {
switch (action.type) {
case Action.UPDATE:
const { nextPlayer, clickedIndex } = action;
//TypeScript error: Property 'nextPlayer' does not exist on type '{ type: Ac
tion; nextPlayer: TicTacToeSymbols; clickedIndex: number; } | { type: Acti
on; }'. TS2339
const newSquares = [...state.squares];
newSquares[clickedIndex] = nextPlayer;
return {
squares: newSquares,
oIsNext: !state.oIsNext
};
case Action.RESET:
return initialState
default:
return state;
}
}
type BoardAction = typeof updateBoard | typeof resetBoard;
export type IBoardActions = ReturnType<BoardAction>;
export function updateBoard(nextPlayer: TicTacToeSymbols, clickedIndex: number) {
return {
type: Action.UPDATE,
nextPlayer,
clickedIndex
};
}
export function resetBoard() {
return {
type: Action.RESET
};
}
为什么会出现此错误?根据错误消息,我的输入似乎是正确的。
【问题讨论】:
-
看来您需要使用discriminated union。请注意,可区分联合需要文字字符串类型,而不是一般的
string类型。现在,IBoardActions的类型为{ type: string; nextPlayer: string; clickedIndex: number; } | { type: string; }。注意type属性的类型是string。 不是字符串文字。 -
根据类型,操作可以是
updateBoard或resetBoard(参见|运算符)。resetBoard动作中不存在下一个玩家。因此,TS 也在抱怨同样的事情。添加可选链接?.或在resetAction中添加nextPlayer -
@Vishnu 可选链接在这种情况下不起作用。可选链接用于访问可为空的属性,而不是可能不存在的属性。必须先缩小联合类型。
-
OP,请尝试在打字稿操场上制作一个最小的可重现示例。包括
UPDATE和RESET的定义。具体来说,它们的类型必须是常量字符串文字才能使可区分的联合起作用。 -
@Chase 是的,我的错。
if条件应该没问题。
标签: reactjs typescript redux