类型声明
在之前的章节中,已经出现了许多类型,这些类型在使用Typescript编写应用的时候十分有用。但是在一般情况下,编辑器和Typescript都是有自动类型推断功能的,所以并不需要吧每一个部分的类型都书写的十分清楚。
最简单的声明Store所使用的类型的方法就是如同以下示例中一样,利用类型参数化的create
函数。
import create from 'zustand';
import { immer } from 'zustand/middleware';
interface GearBoxState {
currentGear: number;
shiftUp: () => void;
shiftDown: () => void;
}
const useGearBox = create<GearBoxState>()(
immer(set => ({
currentGear: 0,
shiftUp: () =>
set(state => {
state.currentGear += 1;
}),
shiftDown: () =>
set(state => {
state.currentGear -= 1;
})
}))
);
在使用类型参数化的create
时,不是直接使用create<T>(set => ({}))
的Store定义形式,而是create<T>()(set => ({}))
,不要丢了泛型参数之后的那一对括号。
以下提供一些在自定义Zustand中间件或者扩展功能的时候可能会用到的类型的定义。
// 所有声明中的State类型都是一个普通的对象。
type State = object;
// State片段就是实际上就是指定State类型的一部分,或者是返回一部分State类型内容的函数。
type ParitalState<T extends State> = Partial<T> | (state: T) => Partial<T>;
// 用于定义从State中选择指定内容的函数,可以是返回一个指定的State,也可以是返回使用指定的一组State组成的新数据结构,还可以是通过计算返回新的内容。
type StateSelector<T extends State, U> = (state: T) => U;
// 用于定义State是否相等的判断函数,主要用于控制State是否更改的判断。
type EqualityChecker<T> = (a: T, b: T) => boolean;
// 用于定义对State更变的监听器函数。
type StateListener<T> = (state: T, previousState: T) => void;
// 用于定义创建对指定Store监听的函数,以及监听注销的函数类型。
interface Subscribe<T extends State> {
(listener: StateListener<T>): () => void;
}
// 定义set函数的类型,用于更新State。
type SetState<T extends State> = (
partial: T | Partial<T> | ((state: T) => T | Partial<T>),
replace?: boolean | undefined
) => void;
// 定义get函数的类型,用于从State中获取指定内容。
type GetState<T extends State> = () => T;
// 定义销毁Store的函数类型。
type Destory = () => void;
// 定义在原生Javascript中定义出的Store类型与组成。这也是一个Store中比较基本的底层功能。
interface StoreApi<T extends State> {
setState: SetState<T>;
getState: GetState<T>;
subscribe: Subscribe<T>;
destory: Destory;
}
// 定义Store中状态的名称,其中StoreMutator就是一个普通的对象,
type StoreMutatorIdentifier = keyof StoreMutator<unknown, unknown>;
// 定义Store中的可变对象,也就是状态。
type Mutate<S, Ms> = Ms extends []
? S
: Ms extends [[infer Mi, infer Ma], ...infer Ms]
? Mutator<StoreMutators<S, Ma>[Mi & StoreMutatorIdentifier], Ms>
: never;
type Get<T, K, F = never> = K extends keyof T ? T[K] : F;
// 定义用于创建Store的函数类型。也就是create函数中所使用的函数类型。
type StateCreator<
T extends State,
Mis extends [StoreMutatorIdentifier, unknown][] = [],
Mos extends [StoreMutatorIdentifier, unknown][] = [],
U = T
> = ((
setState: Get<Mutate<StoreApi<T>, Mis>, 'setState', undefined>,
getState: Get<Mutate<StoreApi<T>, Mos>, 'getState', undefined>,
store: Mutate<StoreApi<T>, Mis>,
) => U);
// 定义create函数的类型声明,可以看到create函数是可以接受一个StateCreator类型的函数作为Store的初始化函数的。
// 同时,用于定义中间件的函数类型也是采用的这个类型。
interface CreateStore {
<T extends State, Mos extends [StoreMutatorIdentifier, unknown][] = []>(
initializer: StateCreator<T, [], Mos>
): Mutate<StoreApi<T>, Mos>;
<T extends State>(): <Mos extends [StoreMutatorIdentifier, unknown][] = []>(
initializer: StateCreator<T, [], Mos>
) => Mutate<StoreApi<T>, Mos>;
}
// 工具类型,用于定义允许提取状态的类型限定。
type ExtractState<S> = S extends { getState: () => infer T } ? T : never;
//工具类型,用于定义适用于React的内容类型。
type WithReact<S extends StoreApi<State>> = S & {
getServerState?: () => ExtractState<S>;
}
// 定义Store Hook的类型,可以看到Store Hook可以直接返回State,或者使用选择器返回要选择的内容。
type UseBoundStore<S extends WithReact<StoreApi<State>>> = {
(): ExtractState<S>;
<U>(
selector: StateSelector<ExtractState<S>, U>,
equals: EqualityChecker<U>
): U
} & S;
上面这些类型定义中有一部分是Zustand中所使用到的工具类型,为了保证能够顺利阅读所有常用的类型,故一并摘抄了进来。在实际项目使用中,可以从其中选择所需要的类型使用。