likes
comments
collection
share

JSDoc:值得信赖的TypeScript替代品

作者站长头像
站长
· 阅读数 4

前言

许多开发人员喜欢使用 TypeScript,因为它具有类型检查功能。然而在打包期间需要额外的转译步骤,既麻烦又浪费时间。本文将向您介绍如何使用 JSDoc 来获取所有相同类型的控件,但只需编写纯 JavaScript 即可,这样不仅能缩短开发时间,还能获得更好的文档!

JavaScript 已成为近来使用最多的脚本语言之一。它以易于在网络平台上编写脚本而闻名。随着JavaScript语言的发展,它已从Java成功时的"玩具"语言发展成为一门成熟的语言,不仅可用于编写小脚本,还可用于编写更多脚本。久而久之,JavaScript本身的缺陷也越来越明显,其中包括:

  • 缺乏静态类型和严格的类型检查:Javascript 是一种灵活的语言,可以将参数传递到不接受参数的函数中,也可以省略必填值等等。但是在静态类型语言的世界中是不会出现这种情况,因为它会在编译时出错。所以这个"特性"也给基于Javascript开发的应用程序带来了很多意料之外的问题。
  • 难以扩展和维护大型代码库:JavaScript 没有提供强大的机制来管理大型代码库,因此随着时间的推移,项目的扩展和维护都将面临巨大的挑战。

JavaScript的救星:TypeScript

2014 年,微软推出了 Typescript v1.0,谁曾想过这将改变整个 JavaScript 生态系统。作为 JavaScript 的超集,TypeScript 解决了上述问题以及更多问题。这使得它在近代也越来越受欢迎。

在本文中,我们将介绍 TypeScript 的一个很好的替代方案JSDoc,它在解决静态类型和可扩展性问题的同时,也消除了 TypeScript 在 JavaScript 生态系统中的这些缺点。

JSDoc为何物?

JSDoc 是 JavaScript 的文档系统,它的工作方式很简单,就是通过一定格式的注释来让编辑器来识别并自动将 描述的类型 引用到编码中,目前主流的编辑器都支持JSDoc,所以请放心食用!本质上是借用了编辑器自身的能力。

JSDoc vs Typescript

JSDoc 和 TypeScript 都解决了编写和维护纯 JavaScript 代码的问题。不过,它们各自采用了不同的方法,但各有利弊。

JSDoc 相对于 Typescript 的优势:

  • 灵活性和兼容性:JSDoc 只是 JavaScript 注释,这意味着它可以添加到任何 JavaScript 代码库中,无论语言版本如何,而且不像 TypeScript 那样与编译器绑定。
  • 代码注释JSDoc 不仅仅可用于类型检查。它可用于添加更多文档、描述函数如何工作以及生成文档网站,所有这些都为提高代码的可维护性和理解性提供了价值。
  • 无编译步骤:这是从 TypeScript 转向 JSDoc 的最重要原因之一。TypeScript 需要编译才能将 Typescript 代码转换为 Javascript,这样浏览器才能理解它,而 JSDoc 则不需要任何其他步骤,因为它们只是 "注释",这是 Javascript 本身支持的功能。与每次进行更改时都使用必要的 Typescript 构建管道相比,这可以简化开发工作流程并提高速度。

使用 JSDoc 的缺点

虽然 JSDoc 与 TypeScript 相比有很多优势,但随着时间的推移,Typescript 的使用也在不断增加。以下是 Typescript 相对于 JSDoc 的一些优势:

  • 更强的静态类型:TypeScript 为类型提供了一个强大的模型,并能在编译时捕捉这些错误。与 JSDoc 不同的是,在 JSDoc 中,这些类型是在代码本身中结束的,并不强制执行。
  • 类型推断TypeScript 可以根据值推断类型。这有助于减少显式类型注解,减少代码冗长。
  • 反编译TypeScript 可以利用其 polyfill 功能采用 JavaScript 语言的最新和未来功能。它能有效地将这些代码转换为可理解的版本,以适用于尚未支持这些功能的浏览器。

如何使用JSDoc

JSDoc 目前在所有现代编辑器中都得到了广泛的支持,开箱即可享用,无需安装任何插件。

给代码块添加说明

如前所述,JSDoc本质上只是一段特定格式的注释

/** The name of the language JSDoc is written for **/ 
const language = "JavaScript"

给值添加类型标记

/**
 * This represents the writer of this blog 
 * @type {string} 
 */
const writerName = "Dev Flow"

最终编辑器的效果如下,已经自动识别成字符串并且给出相关方法提示: JSDoc:值得信赖的TypeScript替代品

就问你,爽不爽?

JSDoc:值得信赖的TypeScript替代品

复杂对象的类型标记

数组

/**
 * @type {Array<string>}
 */
const colours = ['red', 'blue', 'green']

/**
 * @type {number[]}
 */
const primeNumbers = [1, 2, 3, 5, 7]

对象

使用 @typedef 指令可以创建对象类型。

/**
 * @typedef {Object} User - 用户模型 
 * @property {number} id 
 * @property {string} username
 * @property {string} email
 * @property {[number]} postLikes
 * @property {[string]} friends
 */

使用 @type 指定对一个对象进行标记

/** @type {User} */
const person1 = {
  id: 847,
  username: "Elijah",
  email: "elijah@user.com",
  postLikes: [44, 22, 24, 39],
  friends: ["fede", "Elijah"],
};

效果如下: JSDoc:值得信赖的TypeScript替代品

函数(入参、返回值和预期错误类型)

/**
 * 两个数字相除
 * @param {number} dividend - 被除数
 * @param {number} divisor - 除数
 * @returns {number} 返回值
 */
function divideNumbers(dividend, divisor) {
  return dividend / divisor;
}
  • @param 关键字后面定义了一个类型,表示所定义的函数将接受的值。您还可以在连字符(-)后添加一些参数描述。
  • @returns 关键字用于定义函数的返回值。这对大型函数尤其有用。可能很难通过所有代码(包括早期返回)来确定函数的预期返回值。

此外我们还可以使用 @throws 指令添加函数可能抛出的错误。在改进除法函数时,我们可以指定如果被除数为零,函数将返回错误,并在代码本身中进行处理。

/**
 * 两个数字相除
 * @param {number} dividend - 被除数
 * @param {number} divisor - 除数
 * @returns {number} 返回值
 * @throws {ZeroDivisionError} 除数不可以为0
 */
function divideNumbers(dividend, divisor) {
  if (divisor === 0) {
    throw new DivisionByZeroError('Cannot Divide by zero')
  }
  return dividend / divisor;
}

Class类

/**
 * 矩形类
 * @class
 * @classdec 一个具有相等长度的对边和四个直角的四边形
 */
class Rectangle {
  /**
   * 初始化矩形对象。
   * @param {number} length - 矩形的长度。
   * @param {number} width - 矩形的宽度。
   */
  constructor(length, width) {
    this.length = length;
    this.width = width;
  }

  /**
   * 计算矩形的面积。
   * @returns {number} 矩形的面积。
   */
  calculateArea() {
    return this.length * this.width;
  }

  /**
   * 计算矩形的周长。
   * @returns {number} 矩形的周长。
   */
  calculatePerimeter() {
    return 2 * (this.length + this.width);
  }
}

上面是一个简单的矩形类,包含了两个计算面积和周长的方法。

  • @class关键字用于表示需要使用 new 关键字调用一个函数。
  • @classdec用于描述整个类。
  • @params 关键字为需要传入构造函数的参数提供类型和说明

在对类对象进行类型标记时,最重要的是要将粒度细到 构造函数 以及 类中创建的所有方法和变量

将JSDoc导出为文档

使用 JSDoc 的最大好处之一是可以将 JSDoc 文件转换为文档网站,甚至转换为 Typescript,这样就可以获得使用 Typescript 的好处,如在编译时捕捉错误、与 Typescript 项目集成等。

从 JSDoc 文件生成文档

安装JSDoc

npm install -g jsdoc

指定目标文件运行 jsdoc

jsdoc path/to/file.js

查阅文档

jsdoc CLI 会自动创建一个存放文件的 out 文件夹,转到 out/index.html 双击用浏览器打开 JSDoc:值得信赖的TypeScript替代品 这仅仅是默认的jsdoc生成文档的模板,我们也可以对模板进行不同的配置

从 JSDoc 生成 .d.ts 文件

TypeScript 中的 .d.ts 文件代表声明文件,其中包含可被项目中所有 .ts 文件访问的类型。咱可以使用以下步骤从 JSDoc 代码生成这些文件:

在文件夹中安装 tsd-jsdoc

npm install tsd-jsdoc

生成 .d.ts 文件

对于单个文件

jsdoc -t node_modules/tsd-jsdoc/dist -r our/jsdoc/file/path.js

对于多个文件

jsdoc -t node_modules/tsd-jsdoc/dist -r file1.js file2.js file3.js ...

对于整个文件夹

jsdoc -t node_modules/tsd-jsdoc/dist -r src

该工具将文件中的所有类型合并到 out/types.d.ts 中的一个文件中。

注意:前提是已经安装了上一小节中的 jsdoc。如果没有,请先安装后再运行此步骤。

结语

至此,我们已经学会了如何使用JSDoc来生成类型和文档,并且了解了JSDoc的基本用法。JSDoc在以下情况特别有用:当你的TypeScript编译时间/构建步骤对生产力产生负面影响时,它可以发挥特别大的作用。此外在处理旧代码库时非常有用,因为不需要引入任何第三方工具,只要加亿点点注释就好了!