请问zustand的slice里面的属性,如何配置TypeScript类型约束?

参考:官方文档 zustand slice

type Proj = {
  id: number,
  projName: string,
  description: string
}

export const createProjSlice = (set:any, get:any) => ({

  // 1.状态
  projs: Proj[], // 报错
  selectedProj: Proj, // 报错

  // 2.操作状态的actions
  increaseProj: () => set((state:any) => ({ projs: state.projs + ... })),
  removeAllProjs: () => set({ projs: [] }),

})

请问应该如何定义slice呢?(需要结合TypeScript的类型)

尝试都报错:

projs: Proj[],
selectedProj: Proj,

image.png

===

store/index.ts为:

import { create } from 'zustand'

import { createTodoListSlice } from './todolist.store'
import { createBearSlice } from './bears.store'

export const useStore = create((set:any, get:any) => ({
  ...createBearSlice(set, get),
  ...createTodoListSlice(set, get)
}))
阅读 384
3 个回答

试试这个方法:

import { StateCreator, StoreApi } from 'zustand'

type Proj = {
  id: number
  projName: string
  description: string
}

interface ProjSlice {
  projs: Proj[]
  selectedProj: Proj | null
  increaseProj: (proj: Proj) => void
  removeAllProjs: () => void
}

type SliceType = StateCreator<
  ProjSlice, 
  [], 
  [], 
  ProjSlice
>

export const createProjSlice: SliceType = (set) => ({
  projs: [] as Proj[],
  selectedProj: null as Proj | null,

  increaseProj: (proj) => 
    set((state) => ({ 
      projs: [...state.projs, proj]
    })),
  removeAllProjs: () => 
    set({ projs: [] })
})

// store/index.ts
import { create } from 'zustand'

type StoreState = ProjSlice // & OtherSlice

export const useStore = create<StoreState>()((...a) => ({
  ...createProjSlice(...a)
  // ...createOtherSlice(...a)
}))

类型和值是分开的

import { StateCreator } from 'zustand'

type Proj = {
  id: number
  projName: string
  description: string
}

interface ProjSlice {
  projs: Proj[]
  selectedProj: Proj | null
  increaseProj: (proj: Proj) => void
  removeAllProjs: () => void
}

export const createProjSlice: StateCreator<ProjSlice> = (set) => ({
  
  projs: [] as Proj[],
  selectedProj: null as Proj | null,

  // actions
  increaseProj: (proj) => 
    set((state) => ({ 
      projs: [...state.projs, proj]
    })),
  removeAllProjs: () => 
    set({ projs: [] })
})

TypeScript 指南

1.定义状态和操作的类型: 首先,定义你的状态和操作的类型。

import { StateCreator, StoreApi } from 'zustand';

type Proj = {
  id: number;
  projName: string;
  description: string;
};

type ProjSlice = {
  projs: Proj[];
  selectedProj: Proj | null;
  increaseProj: (proj: Proj) => void;
  removeAllProjs: () => void;
};

2.创建 slice: 使用 StateCreator 类型来定义 slice,并确保状态和操作符合类型约束。

  projs: [],
  selectedProj: null,
  increaseProj: (proj: Proj) => set((state) => ({ projs: [...state.projs, proj] })),
  removeAllProjs: () => set({ projs: [] }),
});

3.集成到 store 中: 在 store/index.ts 中,将 slice 集成到你的 store 中。

import { create, StoreApi } from 'zustand';
import { createTodoListSlice } from './todolist.store';
import { createBearSlice } from './bears.store';
import { createProjSlice } from './proj.store'; // 导入 createProjSlice

type StoreState = ReturnType<typeof createBearSlice> & ReturnType<typeof createTodoListSlice> & ReturnType<typeof createProjSlice>;

export const useStore = create<StoreState>((set, get, store: StoreApi<StoreState>) => ({
  ...createBearSlice(set, get, store),
  ...createTodoListSlice(set, get, store),
  ...createProjSlice(set, get, store), // 添加 createProjSlice
}));

TS 错误Xxx 仅表示类型,在此处却作为值使用的万能解法:构造一个符合类型要求的值来占位,例如——

projects: [] as Proj[];

当然,这里的 .selectedProj 可能没有很合适的默认值来占位,如果有的话同样地:

selectedProj: {
  id: -1,
  projName: 'default',
  description: '这只是一个占位用的 Proj'
}

如果确实没有默认值的话,设计上就必须允许空值,因为你不能既不提供有效默认值,又不允许留空。
这种情况下,可以将类型标为 null|Proj ,后续引用这个值的时候, TS 都会要求判空或者断言,如果使用判空,实际上减少了程序出 Bug 的可能性:

selectedProj: null as null|Proj

判空:

if(!signal.selectedProj) return; // 为 null 时不进行操作
// 判空之后, .selectedProj 的类型必然为 Proj
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏