Vuex 4源码学习笔记 - 通过Vuex源码学习TypeScript类型测试(十二)

170 阅读3分钟

这是我参与11月更文挑战的第29天,活动详情查看:2021最后一次更文挑战

在上一篇笔记中:Vuex 4源码学习笔记 - 通过Vuex源码学习E2E测试(十一)

我们通过jestpuppeteer来实现了Vuex的e2e测试。

那么今天我们来继续看另外的TypeScript测试,那么TypeScript测试是什么呢?

首先Vuex的源码是使用JavaScript来开发的,并没有类型的声明,那么Vuex要实现TypeScript的类型就只能通过TypeScript的.d.ts来去描述类型。

image-20211130220500525

我们可以看到在types文件夹下有几个.d.ts的文件,他们都是用来描述TS类型的文件。

image-20211130220729804

比如其中的index.d.ts文件,可以看到声明类型的代码量不小,其实占Vuex源码的很大一部分,但这其实也很重要,对于一个上百万人使用的库来说,做好类型定义是非常有意义的。可能对一些对并不熟悉TypeScript的小伙伴来说这些代码可能并不是很好理解,像我来说平时其实用TypeScript也没有这么深入,有些地方看起来确实需要琢磨琢磨,不过多看就好了。

import { App, WatchOptions, InjectionKey } from "vue";

// augment typings of Vue.js
import "./vue";

import { mapState, mapMutations, mapGetters, mapActions, createNamespacedHelpers } from "./helpers";
import { createLogger } from "./logger";

export * from "./helpers";
export * from "./logger";

export declare class Store<S> {
  constructor(options: StoreOptions<S>);

  readonly state: S;
  readonly getters: any;

  install(app: App, injectKey?: InjectionKey<Store<any>> | string): void;

  replaceState(state: S): void;

  dispatch: Dispatch;
  commit: Commit;

  subscribe<P extends MutationPayload>(fn: (mutation: P, state: S) => any, options?: SubscribeOptions): () => void;
  subscribeAction<P extends ActionPayload>(fn: SubscribeActionOptions<P, S>, options?: SubscribeOptions): () => void;
  watch<T>(getter: (state: S, getters: any) => T, cb: (value: T, oldValue: T) => void, options?: WatchOptions): () => void;

  registerModule<T>(path: string, module: Module<T, S>, options?: ModuleOptions): void;
  registerModule<T>(path: string[], module: Module<T, S>, options?: ModuleOptions): void;

  unregisterModule(path: string): void;
  unregisterModule(path: string[]): void;

  hasModule(path: string): boolean;
  hasModule(path: string[]): boolean;

  hotUpdate(options: {
    actions?: ActionTree<S, S>;
    mutations?: MutationTree<S>;
    getters?: GetterTree<S, S>;
    modules?: ModuleTree<S>;
  }): void;
}

//...

export default _default;

在定义好这些方法或者变量的类型之后,也需要对其进行测试,这就是test/index.ts文件做的事情。

老规矩,还是从package.json看起,我们可以找到一个test:types的命令

"scripts": {
  //...
  "test:types": "tsc -p types/test",
  //...
}

这句命令是什么意思呢?tsc就是我们安装的typescript,然后-p所代表的就是-project的缩写,然后types/test代表的就是项目目录。运行这个命令TS就会首先找到types/test目录下的tsconfig.json配置文件,然后根据配置文件去编译整个目录下的TypeScript文件。

当我们运行这个命令后发现并没有在目录下生成对应的JS文件,因为正常TS是编译成JS文件的,这里就用到了tsconfig.json配置中的一个配置项noEmit。通过打开noEmit,TypeScript并不会输出JavaScript文件,所以可以做一些代码检查工作。

{
  "compilerOptions": {
    "target": "esnext",
    "module": "esnext",
    "moduleResolution": "node",
    "lib": [
      "esnext",
      "dom"
    ],
    "types": [
      "node"
    ],
    "strict": true,
    "noEmit": true // 不会输出JavaScript文件
  },
  "include": [
    "*.ts",
    "../*.d.ts",
    "../../dist/logger.d.ts"
  ]
}

所以通过这样的方式,来测试Vuex中.d.ts的类型声明是否是正确的。

最后,感觉大家的阅读。

一起学习更多前端知识,微信搜索【小帅的编程笔记】,每天更新