Skip to content

在VSCode中为JavaScript代码启用静态类型检查

Updated: at 20:32

很多时候,我们不得不使用 JavaScript 而非 TypeScript 开发项目,作为一个忠实的 TypeScript 用户,我根本无法接受 JS 代码的开发体验,于是开始研究如何在不影响构建流程(已有项目太大,增加 TS 的修改和测试成本太高)的前提下,以影响尽量小的方式为代码增加静态类型检查。

TOC

使用 JSDoc 添加类型信息

比较常见的做法是使用 JSDoc 为 JS 代码添加一定的类型提示,例如:

/**
 * @param {Object} params 函数的参数
 * @param {string} params.requiredProp 必传
 * @param {boolean} [params.optionalProp] 可选
 *
 * @returns {number} 返回值
 */
export function func(params) {
  return 'no error';
}

这样在 hover 查看和使用函数时可以有相应的函数签名提示:

函数hover 函数hover

然而,单纯的使用 JSDoc 并不会对代码有任何实际的约束,即使不按签名来传参也不会有问题。参数类型、返回值类型都不一致,也不会有任何的提示:

错误的输入不会报错

对 JS 代码开启静态类型检查

只是简单提示显然不能满足我们的需求,理想情况下是能在编码过程中对所有类型不兼容的地方进行提示(就像 Typescript 代码一样)。

实际上在 Typescript 2.3 以后已经增加了对 js 代码的类型检查和错误提示:

对于已有项目,一般选择第二种方式,效果如下:

@ts-check

这个提示只是 VSCode 编辑器的一个检查,不影响构建过程(除非项目本身的构建流程就包含了 Typescript 编译且 allowJs 和 checkJs 为 true),因此可以放心的在代码库的任意地方进行使用。

与 Typescript 结合

通过上两节的设置以及可以在 VSCode 中对 JavaScript 代码进行静态检查了,但是还有些问题:

实际上相比单纯的 JSDoc 写法,还有一种更简洁的结合 Typescript 的写法。主要是用到了 JSDoc 的 import。 首先需要单独写一个 ts 文件,例如我一般取名叫 interface.ts 或者 xxx.interface.ts

interface.ts

然后代码中通过 import 的方式进行引用:

import

返回值等也可以用类似的方式引用 ts 文件中导出的类型,同时这个类型文件也可以在多处任意引用。

具体应用举例

React 组件

/**
 * @typedef {import('./interface').Props} Props
 * @typedef {import('./interface').State} State
 * @extends {React.Component<Props, State>}
 */
export default class Component extends React.Component {
  /** @type {State} */
  state = {
    someState: 1,
  };
}
/**
 * @typedef {import('./interface').Props} Props
 * @extends {React.FC<Props>}
 */
const FunctionComponent = props => <div>{props}</div>;

配置文件

可以为各种配置文件提供类型检查和输入的提示

babel.config.js

/**
 *  @type {import('@babel/core').ConfigFunction}
 */
module.exports = api => {
  return {
    presets: [],
  };
};

如果是直接导出 object 的形式可以用:

/**
 * @type {import('@babel/core').TransformOptions}
 */

webpack.config.js

webpack配置,可以提示补全

jest.config.js

jest配置

.eslintrc.js

eslintrc

Reference