I'm making a chess game and I am using Vue 3 and TypeScript with Pinia for the state management.
I want to do something like the following:
export const useStore = defineStore("game", {
state: () => {
return {
moves: [],
gameBoard: getInitialBoard(),
playerTurn: PieceColor.White,
previousPieceSelected: undefined
}
},
updatePreviousPieceSelected(piece: Piece | undefined ) {
this.previousPieceSelected = piece
}
}
})
UpdateGameState.vue
setup() {
const store = useStore()
const previousPieceSelected: Piece | undefined = store.previousPieceSelected;
let playerTurn: PieceColor = store.playerTurn;
const initialGameState: GameState = {
boardState: store.gameBoard,
playerTurn,
};
const updateGameState = (
cellRow: number,
cellCol: number,
currentPiece: Piece
) => {
if (
previousPieceSelected === undefined ||
previousPieceSelected.pieceType === PieceType.None
) {
store.updatePreviousPieceSelected(currentPiece);
}
if (
(previousPieceSelected !== currentPiece && (currentPiece.pieceType === PieceType.None || currentPiece.color !== previousPieceSelected.color))
) {
MovePiece(store.gameBoard, previousPieceSelected, {row: cellRow, col: cellCol} as Position)
store.updatePreviousPieceSelected(undefined);
store.changePlayer();
}
};
However, I get that an error on the following line:
store.updatePreviousPieceSelected(currentPiece);
That currentPiece (of type Piece) is not assignable to type undefined. I found a hack to get this to work by doing the following in my store:
export const useStore = defineStore("game", {
state: () => {
return {
moves: [],
gameBoard: getInitialBoard(),
playerTurn: PieceColor.White,
previousPieceSelected: getInitialPreviousPieceSelected()
}
},
actions: {
changePlayer() {
this.playerTurn =
this.playerTurn === PieceColor.White
? PieceColor.Black
: PieceColor.White;
},
updatePreviousPieceSelected(piece: Piece | undefined ) {
this.previousPieceSelected = piece
}
}
})
function getInitialPreviousPieceSelected(): Piece | undefined {
return undefined;
}
But it feels kluge. Is there another way to type previousPieceSelected in the initial state return?
CodePudding user response:
The type of this.previousPieceSelected
is inferred from the initial state, and it's currently initialized to undefined
, so it thus has a type of undefined
(meaning it can only be assigned a value of undefined
).
Use type assertion on the initial
undefined
value (i.e., theas
keyword plus the desired type ofPiece | undefined
).Also note that optional parameters can be specified with
?:
instead of| undefined
. This is just a simpler way of writing it.
export const useStore = defineStore("game", {
state: () => {
return {
moves: [],
previousPieceSelected: undefined as Piece | undefined, 1️⃣
}
},
actions: { 2️⃣
updatePreviousPieceSelected(piece ?: Piece) {
this.previousPieceSelected = piece
}
}
})