51工具盒子

依楼听风雨
笑看云卷云舒,淡观潮起潮落

Mobx 结合 TypeScript 实现 setState 类型推导

场景

mobx 中,使用 @observable 定义的 state,修改时需要借助 @action 包装才能修改,在变量比较多的情况下,十分不便,这时可以封装一个类似 React 里的 setState 方法,统一修改,在结合 TypeScript 类型推导,可以实现代码联想功能。

使用 TS 遍历指定对象,并形成一个新的类型声明

由于 Mobx Store 本质是一个 object 对象,所以需要声明一个可以遍历某个对象的方法,这里还需要排除 function,我只是需要赋值 mobx 管理的 state 即可,具体代码如下:

type GetStoreState<T extends Record<string, any>> = {
  [Key in keyof T as T[Key] extends Function ? never : Key]: T[Key];
};

以上代码分解:

  1. 使用 type 声明一个 TS 工具方法,接收一个泛型 T extends Record<string, any>,并为泛型缩窄类型,指定类型为可 索引类型
  2. [Key in keyof T as T[Key] extends Function ? never : Key] 分两步理解:
    • Key in keyof T 代表 key 属于传入对象的某一个属性;
    • as T[Key] extends Function ? never : Key 代表一个 js 里的三元表达式,T[Key] extends Function 代表当前遍历的属性值如果为 function 则返回 never,否则返回当前遍历的 key;
  3. T[Key] 代表遍历当前对象的属性值。

具体使用场景示例

完整代码展示

import { action, observable } from 'mobx';

type MenuItemType = { id: string; content: string; };

export type GetStoreState&lt;T extends Record&lt;string, any&gt;&gt; = { [Key in keyof T as T[Key] extends Function ? never : Key]: T[Key]; };

type State = Partial&lt;GetStoreState&lt;BaseStore&gt;&gt;;

class BaseStore { /** 标题 */ @observable title = '';

/** 副标题 */ @observable subTitle = '';

/** 菜单列表 */ @observable menuList: MenuItemType[] = [];

/**

  • 统一更新数据

  • @param params 需要更新的数据

  • @param callback 更新后的回调方法 */ @action setState = (params: State, callback?: () => void) => { Object.keys(params).forEach((key) => { if (key in this) { (this[key as keyof this] as unknown) = params[key as keyof State]; } }); callback?.(); };

/**

  • 示例方法 */ init = () => { this.setState({ title: '我是标题', }); }; }

export default BaseStore;


扩展使用

一个项目中,会存在很多个 store,避免代码冗余,可以将此 store 封装,做基础 store,其他使用场景,统一继承,具体实现:

class BaseStore<State extends Record<string, any>> {
  /**
   * 统一更新数据
   * @param params 需要更新的数据
   * @param callback 更新后的回调方法
   */
  setState = (params: GetStoreState<Partial<State>>, callback?: () => void) => {
    Object.keys(params).forEach((key) => {
      if (key in this) {
        (this[key as keyof this] as unknown) =
          params[key as keyof GetStoreState<Partial<State>>];
      }
    });
    callback?.();
  };
}

class ExampleStore extends BaseStore&lt;ExampleStore&gt; { pageInfo: Record&lt;string, any&gt; = {};

init = () =&gt; { this.setState({ pageInfo: { title: 2, }, }); }; }


相关链接

赞(2)
未经允许不得转载:工具盒子 » Mobx 结合 TypeScript 实现 setState 类型推导