Mobx 结合 TypeScript 实现 setState 类型推导

轩陌

分类: TypeScript 193 2

场景

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<T extends Record<string, any>> = {
  [Key in keyof T as T[Key] extends Function ? never : Key]: T[Key];
};

type State = Partial<GetStoreState<BaseStore>>;

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<ExampleStore> {
  pageInfo: Record<string, any> = {};

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

相关链接

  • 5人 Love
  • 0人 Haha
  • 0人 Wow
  • 0人 Sad
  • 0人 Angry
Mobx、React、TypeScript

作者简介: 轩陌

打赏

生命的意义在于折腾,一直努力成长中,期待梦想实现的那刻。

共 2 条评论关于 “Mobx 结合 TypeScript 实现 setState 类型推导”

Loading...