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\<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,
},
});
};
}`

相关链接

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