如何设置pinia中状态对象的类型?

ave*_*mia 29 typescript vue.js vuejs3 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
    }
  }
})
Run Code Online (Sandbox Code Playgroud)

更新游戏状态.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();
      }
    };
Run Code Online (Sandbox Code Playgroud)

但是,我在以下行中收到错误:

store.updatePreviousPieceSelected(currentPiece);
Run Code Online (Sandbox Code Playgroud)

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;
}
Run Code Online (Sandbox Code Playgroud)

但感觉很杂乱。还有另一种方法可以在初始状态返回中输入 previousPieceSelected 吗?

ton*_*y19 41

的类型this.previousPieceSelected是从初始状态推断出来的,并且当前已初始化为undefined,因此它的类型为undefined(意味着它只能被赋值为undefined)。

\n
    \n
  1. 对初始值使用类型断言undefined(即as关键字加上所需的类型Piece | undefined)。

    \n
  2. \n
  3. ?:另请注意,可以使用代替 来指定可选参数| undefined。这只是一种更简单的编写方式。

    \n
  4. \n
\n
export const useStore = defineStore("game", {\n  state: () => {\n    return {\n      moves: [],\n      previousPieceSelected: undefined as Piece | undefined, 1\xef\xb8\x8f\xe2\x83\xa3\n    }\n  },\n  actions: {                          2\xef\xb8\x8f\xe2\x83\xa3\n    updatePreviousPieceSelected(piece ?: Piece) {\n      this.previousPieceSelected = piece\n    }\n  }\n})\n
Run Code Online (Sandbox Code Playgroud)\n

  • 我喜欢你在代码中使用表情符号来引用你的编号列表! (21认同)

小智 29

或者就像这样

interface IUserState {
  user: null | IUser
}
    
export const useUserStore = defineStore({
  id: 'user',
  state: (): IUserState => ({
    user: null,
  })
...

Run Code Online (Sandbox Code Playgroud)

  • 请不要用“I***”来命名您的接口,这对于 Java 编程语言来说是一种不好的做法。 (2认同)

Ky6*_*6uk 16

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>;
Run Code Online (Sandbox Code Playgroud)

因此可以定义完整类型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 };
Run Code Online (Sandbox Code Playgroud)


oya*_*yal 7

如果没有加载数据。

\n

尝试: https: //pinia.vuejs.org/core-concepts/state.html#typescript

\n

其他:

\n
import {defineStore} from \'pinia\'\n\ninterface Menu {\n  path: string\n  name: string\n  component: string\n  meta: {\n    title: string\n    icon: string\n    affix?: string\n  }\n}\n\nconst useAppStore = defineStore(\'app\', {\n  state: () => ({\n    state: <boolean>false, // boolean\n    message\xef\xbc\x9a <string>\'msg\', // string\n    tagsView: <Menu[]>[] // array\n  })\n})\nexport default useAppStore\n
Run Code Online (Sandbox Code Playgroud)\n


小智 6

例如:

type UserState = {
  login: string
  isPremium: boolean
}


const useUserStore = defineStore<string, UserState>('user', {
  state: () => ({
    login: 'test',
    isPremium: false,
  }),
})
Run Code Online (Sandbox Code Playgroud)