百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 博客教程 > 正文

前端开发利器jsdoc:让我们像写typescript一样写JavaScript

connygpt 2024-11-08 10:32 13 浏览

众所周知的原因,由于JS的语言特性,任何开发工具都不能为JS提供足够好的智能提示,正因为此,微软创造的轮子:typescript,横空出世!

那么,有没有一种不用typescript的解决方案呢?有,那就是今天的主角:jsdoc;这可能是一个大家很少使用的开发利器;它是一个可以使你像写typescript一样写JavaScript;没错,jsdoc主要就是用来给js添加类型信息的;

下面我们看一个简单的函数,这个函数接收一个参数modalElement,由于编辑器不知道它是什么类型,所以在调用它的querySelector方法的时候,无法获得编辑器的智能提示;同样地,编辑器也无法给出btnCloseclick方法的智能提示;

const closeModal = modalElement => {
  if (modalElement) {
    const btnClose = modalElement.querySelector('.el-dialog__close')
    if (btnClose) {
      btnClose.click()
      return true
    }
  }
}

这时候,就该jsdoc出场了;它的语法需要写在多行注释中,因为它不属于js语法的一部分;我们只需给modalElementbtnClose增加一个类型标注,编辑器就知道它们是什么类型,拥有什么能力了;

为函数参数指定类型,使用@param标记,语法:@param {类型} 参数名;为变量指定类型,使用@type标记,语法:@type {类型};代码如下:

/** @param {HTMLDivElement} modalElement */
const closeModal = modalElement => {
  if (modalElement) {
    /** @type {HTMLLinkElement} */
    const btnClose = modalElement.querySelector('.el-dialog__close')
    if (btnClose) {
      btnClose.click()
      return true
    }
  }
}

现在,当我们把指针移入modalElement的时候,就不是一个简单的any类型了,编辑器可以根据文档注释确定它是HTMLDivElement类型,我们在调用它的querySelector方法的时候就能得到编辑器的智能提示;当我们把指针移入click的时候,编辑器告诉我们,这个方法是从HTMLElement继承来的;

@returns标注用于指定函数返回值数据类型;语法:@returns {类型};如下函数返回由HTMLDivElement构成的数组;

/** @returns {HTMLDivElement[]} */
const getAllModals = () => {
  return Array.from(
    document.body.querySelectorAll('.el-dialog__wrapper, .el-drawer__wrapper')
  ).filter(_ => {
    return window.getComputedStyle(_, null).display !== 'none'
  })
}

如下图,当我们调用getAllModals函数返回值的reduce方法的时候,编辑器可以给出智能提示;

我们还可以使用@typedef标记自定义类型;语法:import('模块路径'),用于从模块中导入TS类型定义;&符号用于合并2个类型;如下例子定义了一个名叫RouteConfig的类型,该类型在import('vue-router').RouteConfig的基础上为meta字段增加了number类型的index字段;

/**
 * @typedef {import('vue-router').RouteConfig & {meta: { index: number }}} RouteConfig
 */

如下例子定义了一个EntAccountInfo类型,包含2个字段:数值类型的id和字符串类型的password

/**
 * @typedef {{id: number, password: string}} EntAccountInfo
 */

如果我们的字段比较多,可以使用@property标记定义每个字段;

/**
 * @typedef UserData 用户数据
 * @property {any} entid 租户id
 * @property {string} name 姓名
 * @property {string} workNo 工号
 * @property {string} userId 用户id
 * @property {string} username 登录用户名
 */

我们自定义的类型和内置类型用法完全一样;请看下面例子,包含内置类型和我们上面创建的自定义类型;我们在给对象字段指定类型的时候,可以有2种写法:写在字段名前面或上面;大家觉得哪种风格优雅?

	export const state = Vue.observable({
  /** @type {string[]} */ keeps: [],
  /** @type {RouteConfig[]} */ menus: [],
  /** @type {EntAccountInfo} */ entInfo: {},
  /** @type {UserData} */ userData: {},
})
export const state = Vue.observable({
  /** @type {string[]} */
  keeps: [],
  /** @type {RouteConfig[]} */
  menus: [],
  /** @type {EntAccountInfo} */
  entInfo: {},
  /** @type {UserData} */
  userData: {}
})

我们可以使用管道符为一个变量指定多个可能的类型,请看如下例子,当用户调用该函数的时候,编辑器会提示该函数期望接收一个类型为日期或字符串或数值的参数time

/** @param {Date | string | number} time */
export const getHalfYearAfterTime = time => {
  const date = new Date(time)
  date.setMonth(date.getMonth() + 6)
  date.setDate(date.getDate() - 1)
  return date
}

如果我们的函数有不限个数的参数,可以使用语法:@param {...类型} 参数名,指定参数类型;请看如下例子:

/** @param  {...string} paths */
export const getApiUrl = (...paths) => joinPath(API_BASE, ...paths)

不限参数个数的函数,还有更高级的类型标注写法;请看如下代码,formRequest是一个axios的实例,我们想每次发起post请求的时候少写10来个字符,定义了一个post函数,直接返回了对formRequestpost方法调用;

export const post = (...args) => formRequest.post(...args)

通过编辑器的提示,我们得知axiospost方法有3个不同类型的参数;而我们为了省事,使用了展开运算符,不管传入多少个参数,全部仍给axios实例的post方法;那么,参数类型该如何标注呢?

我们可以使用中括号语法为每个参数指定字段名和类型,例子如下:

/** @param  {[url: string, data?: any, config?: RequestConfig]} args */
export const post = (...args) => formRequest.post(...args)

下图是当指针移入post函数上时,编辑器给出的提示;是不是很酷?

如下是RequestConfig的类型定义,我们扩展了AxiosRequestConfig,为其增加了2个布尔类型字段;现在当我们调用post函数的时候,编辑器就会知道我们的第3个参数config包含这2个布尔类型字段;

/**
 * @typedef {import('axios').AxiosRequestConfig & { needAuth: boolean, saveToken: boolean }} RequestConfig
 */

jsdoc还可以定义泛型类型,语法:@template 泛型名;请看如下例子,TreeNode是一个泛型类型,我们唯一能确定的是它有一个children字段;它具体还包含哪些字段,由泛型T决定;

/**
 * @template T
 * @typedef {T & {children: TreeNode[]}} TreeNode
*/

我们还可以在函数类型标注中使用泛型,请看如下例子,我们定义了一个泛型T,参数data为泛型T数组,返回值为泛型类型TreeNode<T>构成的数组;

/**
 * @template T
 * @param {T[]} data
 * @param {{key: string, parentId: string}} config
 * @returns {TreeNode<T>[]}
 */
export const toTree = (data, config) => {
  const { key = 'id', parentId: pId = 'parentId' } = config || {}
  const ids = data.map(_ => _[key])
  /** @type {TreeNode<T>[]} */
  const result = []
  // ... ...
  return result
}

以上就是我工作中最常用的jsdoc用法,还有很多用法没有涉及到;篇幅有限,大家可以去官网查看文档;希望该文章能助大家的JS技术更上一层楼,感谢阅读!

相关推荐

3分钟让你的项目支持AI问答模块,完全开源!

hello,大家好,我是徐小夕。之前和大家分享了很多可视化,零代码和前端工程化的最佳实践,今天继续分享一下最近开源的Next-Admin的最新更新。最近对这个项目做了一些优化,并集成了大家比较关注...

干货|程序员的副业挂,12个平台分享

1、D2adminD2Admin是一个完全开源免费的企业中后台产品前端集成方案,使用最新的前端技术栈,小于60kb的本地首屏js加载,已经做好大部分项目前期准备工作,并且带有大量示例代码,助...

Github标星超200K,这10个可视化面板你知道几个

在Github上有很多开源免费的后台控制面板可以选择,但是哪些才是最好、最受欢迎的可视化控制面板呢?今天就和大家推荐Github上10个好看又流行的可视化面板:1.AdminLTEAdminLTE是...

开箱即用的炫酷中后台前端开源框架第二篇

#头条创作挑战赛#1、SoybeanAdmin(1)介绍:SoybeanAdmin是一个基于Vue3、Vite3、TypeScript、NaiveUI、Pinia和UnoCSS的清新优...

搭建React+AntDeign的开发环境和框架

搭建React+AntDeign的开发环境和框架随着前端技术的不断发展,React和AntDesign已经成为越来越多Web应用程序的首选开发框架。React是一个用于构建用户界面的JavaScrip...

基于.NET 5实现的开源通用权限管理平台

??大家好,我是为广大程序员兄弟操碎了心的小编,每天推荐一个小工具/源码,装满你的收藏夹,每天分享一个小技巧,让你轻松节省开发效率,实现不加班不熬夜不掉头发,是我的目标!??今天小编推荐一款基于.NE...

StreamPark - 大数据流计算引擎

使用Docker完成StreamPark的部署??1.基于h2和docker-compose进行StreamPark部署wgethttps://raw.githubusercontent.com/a...

教你使用UmiJS框架开发React

1、什么是Umi.js?umi,中文可发音为乌米,是一个可插拔的企业级react应用框架。你可以将它简单地理解为一个专注性能的类next.js前端框架,并通过约定、自动生成和解析代码等方式来辅助...

简单在线流程图工具在用例设计中的运用

敏捷模式下,测试团队的用例逐渐简化以适应快速的发版节奏,大家很早就开始运用思维导图工具比如xmind来编写测试方法、测试点。如今不少已经不少利用开源的思维导图组件(如百度脑图...)来构建测试测试...

【开源分享】神奇的大数据实时平台框架,让Flink&amp;Spark开发更简单

这是一个神奇的框架,让Flink|Spark开发更简单,一站式大数据实时平台!他就是StreamX!什么是StreamX大数据技术如今发展的如火如荼,已经呈现百花齐放欣欣向荣的景象,实时处理流域...

聊聊规则引擎的调研及实现全过程

摘要本期主要以规则引擎业务实现为例,陈述在陌生业务前如何进行业务深入、调研、技术选型、设计及实现全过程分析,如果你对规则引擎不感冒、也可以从中了解一些抽象实现过程。诉求从硬件采集到的数据提供的形式多种...

【开源推荐】Diboot 2.0.5 发布,自动化开发助理

一、前言Diboot2.0.5版本已于近日发布,在此次发布中,我们新增了file-starter组件,完善了iam-starter组件,对core核心进行了相关优化,让devtools也支持对IAM...

微软推出Copilot Actions,使用人工智能自动执行重复性任务

IT之家11月19日消息,微软在今天举办的Ignite大会上宣布了一系列新功能,旨在进一步提升Microsoft365Copilot的智能化水平。其中最引人注目的是Copilot...

Electron 使用Selenium和WebDriver

本节我们来学习如何在Electron下使用Selenium和WebDriver。SeleniumSelenium是ThoughtWorks提供的一个强大的基于浏览器的开源自动化测试工具...

Quick &#39;n Easy Web Builder 11.1.0设计和构建功能齐全的网页的工具

一个实用而有效的应用程序,能够让您轻松构建、创建和设计个人的HTML网站。Quick'nEasyWebBuilder是一款全面且轻巧的软件,为用户提供了一种简单的方式来创建、编辑...