zustand ts类型解析

192 阅读2分钟

注:zustand版本4.5.2

一、没有中间情况

基本用法

注:例子1

import { create } from 'zustand';

interface BearState {
  bears: number;
  increase: (by: number) => void;
}

export const useBearStore = create<BearState>((set) => ({
  bears: 0,
  increase: (by) => set((state) => ({ bears: state.bears + by })),
}));

类型解析

type CreateStore = {
    // 第一个函数重载
    <T, Mos extends [StoreMutatorIdentifier, unknown][] = []>(initializer: StateCreator<T, [], Mos>): Mutate<StoreApi<T>, Mos>;
     // 第二个函数重载
    <T>(): <Mos extends [StoreMutatorIdentifier, unknown][] = []>(initializer: StateCreator<T, [], Mos>) => Mutate<StoreApi<T>, Mos>;
};

注:命中第一个函数重载的。

StateCreator

export type StateCreator<T, Mis extends [StoreMutatorIdentifier, unknown][] = [], Mos extends [StoreMutatorIdentifier, unknown][] = [], U = T> = ((setState: Get<Mutate<StoreApi<T>, Mis>, 'setState', never>, getState: Get<Mutate<StoreApi<T>, Mis>, 'getState', never>, store: Mutate<StoreApi<T>, Mis>) => U) & {
    $$storeMutators?: Mos;
};
因为Mis类型为[],StateCreator类型即为
export type StateCreator<T, [], Mos extends [StoreMutatorIdentifier, unknown][] = [], U = T> = ((setState: Get<Mutate<StoreApi<T>, []>, 'setState', never>, getState: Get<Mutate<StoreApi<T>, []>, 'getState', never>, store: Mutate<StoreApi<T>, []>) => U) & {
  $$storeMutators?: Mos;
};
Mos类型被推断为[],StateCreator类型即为

image.png

export type StateCreator<T, [], [], U = T> = ((setState: Get<Mutate<StoreApi<T>, []>, 'setState', never>, getState: Get<Mutate<StoreApi<T>, []>, 'getState', never>, store: Mutate<StoreApi<T>, []>) => U) & {
  $$storeMutators?: [];
};
StoreApi类型
export interface StoreApi<T> {
    setState: SetStateInternal<T>;
    getState: () => T;
    getInitialState: () => T;
    subscribe: (listener: (state: T, prevState: T) => void) => () => void;
    /**
     * @deprecated Use `unsubscribe` returned by `subscribe`
     */
    destroy: () => void;
}
SetStateInternal

注:比较简单,不作展开

type SetStateInternal<T> = {
    _(partial: T | Partial<T> | {
        _(state: T): T | Partial<T>;
    }['_'], replace?: boolean | undefined): void;
}['_'];
Mutate
export type Mutate<S, Ms> = number extends Ms['length' & keyof Ms] ? S : Ms extends [] ? S : Ms extends [[infer Mi, infer Ma], ...infer Mrs] ? Mutate<StoreMutators<S, Ma>[Mi & StoreMutatorIdentifier], Mrs> : never;

由上面类型推断,Ms类型为[],keyof []length属性;则'length' & keyof Ms等于 'length';数组的length属性类型为number;因此返回S,即BearState

Get

获取对象某个属性值

type Get<T, K, F> = K extends keyof T ? T[K] : F;

UseBoundStore

export type UseBoundStore<S extends WithReact<ReadonlyStoreApi<unknown>>> = {
  // ExtractState:指定getState
  (): ExtractState<S>
  <U>(selector: (state: ExtractState<S>) => U): U
  /**
   * @deprecated Use `createWithEqualityFn` from 'zustand/traditional'
   */
  <U>(
    selector: (state: ExtractState<S>) => U,
    equalityFn: (a: U, b: U) => boolean,
  ): U
} & S
ExtractState
type ExtractState<S> = S extends { getState: () => infer T } ? T : never

没有中间情况,zustand推荐写法

注:例子2;和例子1区别是使用柯里化调用()(...)Ms类型推断为[],类型同例子1

import { create } from 'zustand';

interface BearState {
  bears: number;
  increase: (by: number) => void;
}

export const useBearStore = create<BearState>()((set) => ({
  bears: 0,
  increase: (by) => set((state) => ({ bears: state.bears + by })),
}));

有中间件情况

import { create } from 'zustand';
import { immer } from 'zustand/middleware/immer';

interface BearState {
  bears: number;
  increase: (by: number) => void;
}

export const useBearStore = create<BearState>()(
  immer((set) => ({
    bears: 0,
    increase: (by) => set((state) => ({ bears: state.bears + by })),
  })),
);

类型解析

type CreateStore = {
    // 第一个函数重载
    <T, Mos extends [StoreMutatorIdentifier, unknown][] = []>(initializer: StateCreator<T, [], Mos>): Mutate<StoreApi<T>, Mos>;
     // 第二个函数重载
    <T>(): <Mos extends [StoreMutatorIdentifier, unknown][] = []>(initializer: StateCreator<T, [], Mos>) => Mutate<StoreApi<T>, Mos>;
};

注:命中第二个函数重载的。

immer

注:immer类型推断如下

image.png

Immer类型定义

type Immer = <T, Mps extends [StoreMutatorIdentifier, unknown][] = [], Mcs extends [StoreMutatorIdentifier, unknown][] = []>(initializer: StateCreator<T, [...Mps, ['zustand/immer', never]], Mcs>) => StateCreator<T, Mps, [['zustand/immer', never], ...Mcs]>;

只有immer一个中间件时

Mps类型为[],Mcs类型为[]

简化后,如下

type Immer = <T, [], []>(initializer: StateCreator<T, [...[], ['zustand/immer', never]], []>) => StateCreator<T, [], [['zustand/immer', never], ...[]]>;

省略拓展运算符后如下

type Immer = <T, [], []>(initializer: StateCreator<T, [['zustand/immer', never]], []>) => StateCreator<T, [], [['zustand/immer', never]]>;

StateCreator

export type StateCreator<T, Mis extends [StoreMutatorIdentifier, unknown][] = [], Mos extends [StoreMutatorIdentifier, unknown][] = [], U = T> = ((setState: Get<Mutate<StoreApi<T>, Mis>, 'setState', never>, getState: Get<Mutate<StoreApi<T>, Mis>, 'getState', never>, store: Mutate<StoreApi<T>, Mis>) => U) & {
    $$storeMutators?: Mos;
};
因为Mis类型为[['zustand/immer', never]],StateCreator类型即为
export type StateCreator<T, [['zustand/immer', never]], Mos extends [StoreMutatorIdentifier, unknown][] = [], U = T> = ((setState: Get<Mutate<StoreApi<T>, [['zustand/immer', never]]>, 'setState', never>, getState: Get<Mutate<StoreApi<T>, [['zustand/immer', never]]>, 'getState', never>, store: Mutate<StoreApi<T>, [['zustand/immer', never]]>) => U) & {
  $$storeMutators?: Mos;
};
Mos类型被推断为[],StateCreator类型即为
export type StateCreator<T, [['zustand/immer', never]], [], U = T> = ((setState: Get<Mutate<StoreApi<T>, [['zustand/immer', never]]>, 'setState', never>, getState: Get<Mutate<StoreApi<T>, [['zustand/immer', never]]>, 'getState', never>, store: Mutate<StoreApi<T>, [['zustand/immer', never]]>) => U) & {
  $$storeMutators?: [];
};

Mutate

export type Mutate<S, Ms> = number extends Ms['length' & keyof Ms] ? S : Ms extends [] ? S : Ms extends [[infer Mi, infer Ma], ...infer Mrs] ? Mutate<StoreMutators<S, Ma>[Mi & StoreMutatorIdentifier], Mrs> : never;

注:这里keyof [['zustand/immer', never]]为与[]同类型,包含length属性;Ms['length']则返回1,因为只有一个中间件(即数组长度为1),因此走下面逻辑。Ma类型为never

Mutate<StoreMutators<S, never>[Mi & StoreMutatorIdentifier], []> 

StoreMutators

注:immer中间件重写了StoreMutators类型

declare module '../vanilla' {
    // 重写了StoreMutators接口类型
    interface StoreMutators<S, A> {
        ['zustand/immer']: WithImmer<S>;
    }
}
// Immer类型覆盖Store原有类型
type Write<T, U> = Omit<T, keyof U> & U;
type SkipTwo<T> = T extends {
    length: 0;
} ? [] : T extends {
    length: 1;
} ? [] : T extends {
    length: 0 | 1;
} ? [] : T extends [unknown, unknown, ...infer A] ? A : T extends [unknown, unknown?, ...infer A] ? A : T extends [unknown?, unknown?, ...infer A] ? A : never;
type WithImmer<S> = Write<S, StoreImmer<S>>;
// ...a支持更多参数,SKipTwo是忽略前面参数;目前zustand只支持partial, replace这两个参数
type StoreImmer<S> = S extends {
    getState: () => infer T;
    setState: infer SetState;
} ? SetState extends (...a: infer A) => infer Sr ? {
    setState(nextStateOrUpdater: T | Partial<T> | ((state: Draft<T>) => void), shouldReplace?: boolean | undefined, ...a: SkipTwo<A>): Sr;
} : never : never;

多个中间件使用

import { create } from 'zustand';
import { immer } from 'zustand/middleware/immer';
import { persist, createJSONStorage } from 'zustand/middleware';

interface BearState {
  bears: number;
  increase: (by: number) => void;
}

export const useBearStore = create<BearState>()(
  persist(
    immer((set) => ({
      bears: 0,
      increase: (by) => set((state) => ({ bears: state.bears + by })),
    })),
    {
      name: 'food-storage', // name of the item in the storage (must be unique)
      storage: createJSONStorage(() => sessionStorage), // (optional) by default, 'localStorage' is used
    },
  ),
);

image.png

不同地方只有 Mutate

export type Mutate<S, Ms> = number extends Ms['length' & keyof Ms] ? S : Ms extends [] ? S : Ms extends [[infer Mi, infer Ma], ...infer Mrs] ? Mutate<StoreMutators<S, Ma>[Mi & StoreMutatorIdentifier], Mrs> : never;

注:这里是递归整合中间件新增属性 注:这里keyof [['zustand/immer', never]]为与[]同类型,包含length属性;Ms['length']则返回2,因为有两个中间件,因此走下面逻辑。Ma类型为never