如何在 pinia 中设置状态对象的类型?
How to set the type for the state object in pinia?
我正在制作国际象棋游戏,我正在使用 Vue 3 和 TypeScript 以及 Pinia 进行状态管理。
我想做如下事情:
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();
}
};
但是,我在以下行中收到错误消息:
store.updatePreviousPieceSelected(currentPiece);
currentPiece(属于 Piece 类型)不可分配给 undefined 类型。我通过在我的商店中执行以下操作找到了使它起作用的技巧:
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;
}
但感觉很麻烦。在初始状态return中输入previousPieceSelected还有另一种方法吗?
this.previousPieceSelected
的类型是从初始状态推断出来的,目前它被初始化为undefined
,因此它具有undefined
的类型(意味着它只能被分配undefined
).
的值
在初始 undefined
值上使用 type assertion(即,as
关键字加上所需的 Piece | undefined
类型)。
另请注意,可以使用 ?:
而非 | undefined
指定可选参数。这只是一种更简单的写法。
export const useStore = defineStore("game", {
state: () => {
return {
moves: [],
previousPieceSelected: undefined as Piece | undefined, 1️⃣
}
},
actions: { 2️⃣
updatePreviousPieceSelected(piece ?: Piece) {
this.previousPieceSelected = piece
}
}
})
或者像这样
interface IUserState {
user: null | IUser
}
export const useUserStore = defineStore({
id: 'user',
state: (): IUserState => ({
user: null,
})
...
getInitialBoard()
来自哪里?
那是进口的吗?
您的初始化数据不应该是您的计算值。这更多是 pinia 中“getters”的功能。你有“状态”、“吸气剂”和“动作”。状态通常只是初始化的类型化变量。 getter 是在不改变状态数据的情况下计算出的可返回值。动作改变状态数据。您应该只使用存储操作更改状态数据,而不是从 pinia 外部的组件实例中更改状态数据。所有的数据,即真相的来源,一直都在 pinia 中。
以这种方式让您的商店井井有条:
// conceptual model e.g.
pinia {
state: () => {
return { data }
},
getters: {
// doesn't change data
getter: (state) => state.data.returnComputedState(),
},
actions: {
// changes data
action: () => this.data = mutateTheData(this.data),
},
}
例如:
type UserState = {
login: string
isPremium: boolean
}
const useUserStore = defineStore<string, UserState>('user', {
state: () => ({
login: 'test',
isPremium: false,
}),
})
defineStore
是 TypeScript 中的通用函数,它接受两个参数,存储 ID 和状态。
/**
* Creates a `useStore` function that retrieves the store instance
*
* @param id - id of the store (must be unique)
* @param options - options to define the store
*/
export declare function defineStore<Id extends string, S extends StateTree = {}, G extends _GettersTree<S> = {}, A = {}>(id: Id, options: Omit<DefineStoreOptions<Id, S, G, A>, 'id'>): StoreDefinition<Id, S, G, A>;
因此可以定义 fully-typed State
和商店名称。
import { defineStore } from 'pinia';
interface State {
borks: string[];
isWoof: boolean;
}
interface Getters {}
interface Actions {
addBork(bork: string) => void;
}
const useBorkStore = defineStore<'bork', State, Getters, Actions>('bork', {
state: () => {
return {
borks: [],
isWoof: false
}
},
actions: {
addBork(bork: string) {
this.borks.push(bork);
}
}
})
export { useBorkStore };
我正在制作国际象棋游戏,我正在使用 Vue 3 和 TypeScript 以及 Pinia 进行状态管理。
我想做如下事情:
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();
}
};
但是,我在以下行中收到错误消息:
store.updatePreviousPieceSelected(currentPiece);
currentPiece(属于 Piece 类型)不可分配给 undefined 类型。我通过在我的商店中执行以下操作找到了使它起作用的技巧:
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;
}
但感觉很麻烦。在初始状态return中输入previousPieceSelected还有另一种方法吗?
this.previousPieceSelected
的类型是从初始状态推断出来的,目前它被初始化为undefined
,因此它具有undefined
的类型(意味着它只能被分配undefined
).
在初始
undefined
值上使用 type assertion(即,as
关键字加上所需的Piece | undefined
类型)。另请注意,可以使用
?:
而非| undefined
指定可选参数。这只是一种更简单的写法。
export const useStore = defineStore("game", {
state: () => {
return {
moves: [],
previousPieceSelected: undefined as Piece | undefined, 1️⃣
}
},
actions: { 2️⃣
updatePreviousPieceSelected(piece ?: Piece) {
this.previousPieceSelected = piece
}
}
})
或者像这样
interface IUserState {
user: null | IUser
}
export const useUserStore = defineStore({
id: 'user',
state: (): IUserState => ({
user: null,
})
...
getInitialBoard()
来自哪里?
那是进口的吗?
您的初始化数据不应该是您的计算值。这更多是 pinia 中“getters”的功能。你有“状态”、“吸气剂”和“动作”。状态通常只是初始化的类型化变量。 getter 是在不改变状态数据的情况下计算出的可返回值。动作改变状态数据。您应该只使用存储操作更改状态数据,而不是从 pinia 外部的组件实例中更改状态数据。所有的数据,即真相的来源,一直都在 pinia 中。
以这种方式让您的商店井井有条:
// conceptual model e.g.
pinia {
state: () => {
return { data }
},
getters: {
// doesn't change data
getter: (state) => state.data.returnComputedState(),
},
actions: {
// changes data
action: () => this.data = mutateTheData(this.data),
},
}
例如:
type UserState = {
login: string
isPremium: boolean
}
const useUserStore = defineStore<string, UserState>('user', {
state: () => ({
login: 'test',
isPremium: false,
}),
})
defineStore
是 TypeScript 中的通用函数,它接受两个参数,存储 ID 和状态。
/**
* Creates a `useStore` function that retrieves the store instance
*
* @param id - id of the store (must be unique)
* @param options - options to define the store
*/
export declare function defineStore<Id extends string, S extends StateTree = {}, G extends _GettersTree<S> = {}, A = {}>(id: Id, options: Omit<DefineStoreOptions<Id, S, G, A>, 'id'>): StoreDefinition<Id, S, G, A>;
因此可以定义 fully-typed State
和商店名称。
import { defineStore } from 'pinia';
interface State {
borks: string[];
isWoof: boolean;
}
interface Getters {}
interface Actions {
addBork(bork: string) => void;
}
const useBorkStore = defineStore<'bork', State, Getters, Actions>('bork', {
state: () => {
return {
borks: [],
isWoof: false
}
},
actions: {
addBork(bork: string) {
this.borks.push(bork);
}
}
})
export { useBorkStore };