最近在用我的 axiosist 做单元测试的时候,发现在 VSCode 下用这个库写代码,自动提示不是特别友好。想把它做的友好的最简单方法就是用 TypeScript 重写一下,但是因为目前采用 commonjs 的模块直接 module.exports = axiosist 的方式导出的默认模块,在 TypeScript 下就要用官方很不推荐的 export = axiosist 的语法来替代。再加上一大堆的编译发布流程,感觉改动太大了。所以打算参照 index.js 先手撸一个 index.d.ts 出来用。那么遇到的问题就是,如何验证我这个手撸的 index.d.ts 是符合 index.js 的定义?看了下大家的普遍做法,是再写一个 TypeScript 的单元测试,但是我觉得既然我已经有一个 JavaScript 写的单元测试了,而 TypeScript 现在已经可以编译 JavaScript 文件了,能不能把 JavaScript 的单元测试文件直接利用起来呢?于是我开始了尝试:

首先我先去掉我的 index.d.ts 文件,用 tsc 跑一下 test.js

$ npx tsc test.js

报错不支持 .js 这个后缀,我们加上 --allowJs 启用 JavaScript 文件的支持

$ npx tsc --allowJs test.js

报错不能覆盖现有文件,我们加上 --noEmit 去掉输出

$ npx tsc --allowJs --noEmit test.js

运行成功了,但是这并不是我们想要的,因为它并没有检查类型。因为没有写任何类型的情况下,所有的类型都是 any,所以我们加上 --strict 参数,启用严格模式,禁止使用 any 类型

$ npx tsc --allowJs --noEmit --strict test.js

仍然没有报错,说明 JavaScript 文件虽然参与编译,但是并没有参与类型检查,于是我们加上 --checkJs 参数,使 JavaScript 文件参与到类型检查中。

$ npx tsc --allowJs --noEmit --strict --checkJs test.js

成功了,所有的 any 报错都出来了。这个时候把 index.d.ts 启用,我们就可以测试我们写的 index.d.ts 是否符合库代码了。

把刚才的参数整理成 tsconfig.json 文件,就是这样

{
    "compilerOptions": {
        "allowJs": true,
        "checkJs": true,
        "noEmit": true,
        "strict": true,
    },
    "files": [
        "test.js"
    ]
}

放到项目根目录,我们就有了一个不用维护任何 TypeScript 逻辑代码,只用现有的 JavaScript 文件就可以验证 d.ts 文件是否符合要求的方法,当然,前提是 JavaScript 的测试要尽量全面,调用了所有接口。这样才能尽可能保证 TypeScript 在验证类型时不会发生漏验的情况。