JSDoc 真能取代 TypeScript?

这几个月,想必大家都听到过一个新闻:

Svelte 弃用 TypeScript,改用 JSDoc 了。

TypeScript 我们知道,是用来给 JS 加上类型的,可以实现类型提示和编译时的类型检查。

那 JSDoc 能够完成一样的功能么?Svelte 是出于什么原因弃用 TS 的呢?

先不着急回答这个问题。

我们总得先了解下 JSDoc:

可能大家认为的 JSDoc 是这个东西:

在代码的注释上加上类型的标识,然后通过 jsdoc 命令行工具,就可以直接生成文档。

比如这样的文档:

确实,这个是 JSDoc 最初的含义。

但我们说的 JSDoc 并不是这个,而是 TS 基于 JSDoc 语法实现的,在注释里给代码添加类型的语法。

文档在这里:

ts 支持在 js 文件的注释里,通过 JSDoc 的语法给它加上类型。

至于有什么意义,那可就太多了。

比如一个 JS 的配置文件,你想在写配置的时候能有提示,就可以用 JSDoc:

这里注释里的 @type 就是 JSDoc 声明类型的语法。

在 vite 文档里,你可以看到对 JSDoc 的支持:

我们自己试一下:

mkdir jsdoc-test
cd jsdoc-test
npm init -y

创建项目和 package.json。

然后安装 typescript:

npm install --save-dev typescript

创建 tsconfig.json 文件:

npx tsc --init

生成的 tscconfig.json 太多注释了,我们删一下:

然后创建 src/index.ts

function add(a: number, b: number) {return a + b;
}

这样在用到这个 add 的时候,就会做类型检查:

在 tsconfig.json 里 include 一下:

之后执行编译:

npx tsc

生成的代码是这样的:

这个是 ts 的编译流程,大家都很熟悉。

现在问题来了,我有一个 src/index2.js,怎么实现一样的类型检查呢?

这样写:

/*** @param {number} a  参数aaa* @param {number} b  参数bbb*/
function add2(a, b) {return a + b;
}

注释里的就是 JSDoc 的语法。

但现在并没有报类型错误:

需要在 tsconfig 里开启:

allowJS 是允许编译 JS,checkJS 是在编译 JS 的时候也做类型检查。

开启后你就会发现,js 文件里也会做类型检查了:

hover 上去的时候,会提示类型信息:

注意,这可不是用 ts 语法声明的类型,而是用 JSDoc 写的。

然后我们开启 dts:

再编译:

npx tsc

可以看到同样能产出 d.ts 类型声明文件:

而这时候产物的 JS 代码和源码差别不大:

因为本来 JSDoc 就是在注释里的,类型检查也好、生成 dts 也好,都不用改动源码。

这就是 JSDoc 最大的好处:无侵入的给 JS 加上类型,拥有和 ts 一样的类型检查、类型提示、生成 dts 等功能,但却不需要编译,因为 JS 代码可以直接跑。

有同学可能会说,就声明个函数类型就和 ts 一样了?

那肯定不止这么点语法,我们再看几个:

比如可以用 @type 给变量声明类型:

这里可以是各种类型,比如函数类型:

如果类型被多处用到,可以用 @typedef 抽出来,单独命名:

你还可以把这个类型放到 dts 文件里,在这里 import 进来用:

比如我把它放到 guang.d.ts 里:

然后这样引入用:

这样就避免了在 @typedef 里写大段类型定义了,不然代码写多了就不好维护了。

这样就可以在 dts 里定义类型,然后在 js 里通过 JSDoc 引入来用。

dts + JSDoc 是绝佳搭配。

然后我们继续看 JSDoc 的函数类型定义:

这分别是可选参数、参数默认值、返回值类型的语法。

还有同学说,那 ts 的泛型呢?这个 JSDoc 不支持的吧?

当然也是支持的,这样写:

通过 @template 声明类型参数,然后下面就可以用了。

泛型都可以用,那基于泛型的类型编程,也就是类型体操当然也可以玩:

一般这种复杂类型还是抽离到 dts 里,然后 @type {import(‘xxx’).xxx} 引入比较好。

再就是 class 了,这个自然也是支持的。

比如声明一个泛型类:

这段类型大家能看懂么?

就是声明了一个泛型类,有一个类型参数 T。它通过 @extends 继承了 Set 类型。

它有个 name 属性的类型为 T,并且还声明了构造器和 sleep 方法的类型。

用一下试试:

name 和 sleep 的类型,继承的 Set 的类型,都没问题。

这就是 JSDoc 定义 class 类型的方式。

综上,用 JSDoc 可以定义变量、函数、class、泛型等,可以从别的 dts 文件引入类型。

基本上 ts 能做的,JSDoc 也都可以。

但是,JSDoc 语法毕竟是在注释里的,多了一大坨东西,而且写起来也不如 ts 语法直观。

所以,一般没必要这样写,除非你是给 JS 加类型。

那 svelte 是出于什么原因选择了 JSDoc 的方式呢?

看下那个 pr 就知道了:

直接看官方回复:

也就是说,用 ts 的语法,需要编译后才能调试,这样需要再 sourcemap 一次才能对应到源码。

但是用 JSDoc 的方式,不用编译就可以直接调试。

估计是遇到了啥 VSCode 调试上的问题。

然后下面还有个 VSCode 调试器的维护者评论说,有任何调试相关的问题可以找我:

总之,svelte 选择从 ts 转成 JSDoc + dts 并不是因为 ts 有啥问题,主要是为了调试方便。

那我们再看下它怎么用的吧:

可以看到,是 js 文件里用 JSDoc 来声明类型:

然后复杂类型在 dts 里定义,然后这里引入:

就和我们刚才测试的一样。

总结

这几个月经常听到知名开源项目抛弃 ts 拥抱 JSDoc 的新闻,我们一起探究了一下。

JSDoc 是在 js 的注释里通过 @type、@typedef、@template、@param 等来定义类型,然后开启 checkJS 和 allowJS 的配置之后,tsc 就可以对 js 做类型检查。

ts 里可以定义的类型,在 JSDoc 里都可以定义,比如变量、函数、class、泛型,甚至类型编程等。复杂的类型还可以抽离到 dts 里,在 @type 里引入。

也就是说 JSDoc 确实可以替代 ts。

然后我们看了 svelte 选择 JSDoc 的原因,只是为了调试方便。这样不用编译就可以直接跑 js 代码,可以直接定位到源码。而且这样也能利用 ts 的类型提示和检查的能力。

所以很多人就说 svelte 抛弃了 ts。

这叫抛弃么?

并不是,JSDoc 只是另一种使用 ts 的方式而已。

更多内容可以看我的小册《TypeScript 类型体操通关秘籍》

最后

欢迎关注"所谓前端"微信公众号,大家一起交流
点击扫码关注

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/676156.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

图像处理常用算法—6个算子 !!

目录 前言 1、Sobel 算子 2、Isotropic Sobel 算子 3、Roberts 算子 4、Prewitt 算子 5、Laplacian算子 6、Canny算子 前言 同图像灰度不同,边界处一般会有明显的边缘,利用此特征可以分割图像。 需要说明的是:边缘和物体间的边界并不…

Android应用图标微技巧,8.0系统中应用图标的适配

大家好,2018年的第一篇文章到的稍微有点迟,也是因为在上一个Glide系列结束之后一直还没想到什么好的新题材。 现在已经进入了2018年,Android 8.0系统也逐渐开始普及起来了。三星今年推出的最新旗舰机Galaxy S9已经搭载了Android 8.0系统,紧接着小米、华为、OV等国产手机厂…

一句话总结Docker与K8S的关系

一句话总结:Docker只是容器的一种,它面向的是单体,K8S可以管理多种容器,它面向的是集群,Docker可以作为一种容器方案被K8S管理。下文继续具体介绍。 1、容器的核心概念 介绍这几个核心概念:OCI、CR、Runc、…

C语言指针运算

指针运算 指针加法意味着地址向上移动若干个目标指针减法意味着地址向下移动若干个目标示例: int a 100; int *p &a; // 指针 p 指向整型变量 aint *k1 p 2; // 向上移动 2 个目标(2个int型数据) int *k2 p - 3; // 向下移动 3 个…

PWM输入输出

PWM(Pulse Width Modulation)即脉冲宽度调制,在具有惯性的系统中,可以通过对一系列脉冲的宽度进行制,来等效地获得所需要的模拟参量,常应用于电机控速、开关电源等领域。 PWM参数 PWM 中有三个重要参数&…

寒假作业-day7

1>现有文件test.c\test1.c\main.c , 请编写Makefile. 代码: CCgcc EXEstr OBJS$(patsubst %.c,%.o,$(wildcard *.c)) CFLAGS-c -oall:$(EXE)$(EXE):$(OBJS)$(CC) $^ -o $%.o:%.c$(CC) $(CFLAGS) $ $^head.o:head.hclean:rm $(OBJS) $(EXE) 2>C编程实现&…

封装sku组件

1. 准备模板渲染规格数据 使用Vite快速创建一个Vue项目&#xff0c;在项目中添加请求插件axios&#xff0c;然后新增一个SKU组件&#xff0c;在根组件中把它渲染出来&#xff0c;下面是规格内容的基础模板 <script setup> import { onMounted, ref } from vue import axi…

NOVATEK显示技术系列之CEDSCHPI Training差异简介

CEDS的数据封包格式&#xff1a;首先CEDS数据封包包括三个部分&#xff1a; Training Pattern即Phase1Control Data 即 Phase2RGB Data 即Phase3 Power on Timing&#xff1a; 工作原理&#xff1a; Power ON时&#xff0c;TCON会发Training Pattern&#xff0c;当COF接受Tr…

江科大STM32 终

目录 SPI协议10.1 SPI简介W25Q64简介10.3 SPI软件读写W25Q6410.4 SPI硬件外设读写W25Q64 BKP备份寄存器、PER电源控制器、RTC实时时钟11.0 Unix时间戳代码示例&#xff1a;读写备份寄存器BKP11.2 RTC实时时钟 十二、PWR电源控制12.1 PWR简介代码示例&#xff1a;修改主频12.3 串…

分享90个行业PPT,总有一款适合您

分享90个行业PPT&#xff0c;总有一款适合您 90个行业PPT下载链接&#xff1a;https://pan.baidu.com/s/1bHvhk_42-IFAjNdjPPtMZw?pwd8888 提取码&#xff1a;8888 Python采集代码下载链接&#xff1a;采集代码.zip - 蓝奏云 学习知识费力气&#xff0c;收集整理更不易…

106. 从中序与后序遍历序列构造二叉树 - 力扣(LeetCode)

题目描述 给定两个整数数组 inorder 和 postorder &#xff0c;其中 inorder 是二叉树的中序遍历&#xff0c; postorder 是同一棵树的后序遍历&#xff0c;请你构造并返回这颗 二叉树 。 题目示例 输入&#xff1a;inorder [9,3,15,20,7], postorder [9,15,7,20,3] 输出&a…

B2078 含 k 个 3 的数(洛谷)

题目描述 输入两个正整数 m 和 k&#xff0c;其中 1<m≤&#xff0c;1<k≤15 &#xff0c;判断 m 是否恰好含有 k 个 3&#xff0c;如果满足条件&#xff0c;则输出 YES&#xff0c;否则&#xff0c;输出 NO。 输入格式 输入一行&#xff0c;为两个整数 m,k&#xff0…

揭开Markdown的秘籍:标题|文字样式|列表

&#x1f308;个人主页&#xff1a;聆风吟 &#x1f525;系列专栏&#xff1a;Markdown指南、网络奇遇记 &#x1f516;少年有梦不应止于心动&#xff0c;更要付诸行动。 文章目录 &#x1f4cb;前言一. ⛳️Markdown 标题二. ⛳️Markdown 文字样式2.1 &#x1f514;斜体2.2 &…

python智慧养老系统—养老信息服务平台vue

本论文中实现的智慧养老系统-养老信息服务平台将以管理员和用户的日常信息维护工作为主&#xff0c;主要涵盖了系统首页&#xff0c;个人中心&#xff0c;用户管理&#xff0c;养老资讯管理&#xff0c;养生有道管理&#xff0c;养老机构管理&#xff0c;系统管理等功能&#x…

海外云手机——平台引流的重要媒介

随着互联网的飞速发展&#xff0c;跨境电商、短视频引流以及游戏行业等领域正经历着迅猛的更新换代。在这个信息爆炸的时代&#xff0c;流量成为至关重要的资源&#xff0c;而其中引流环节更是关乎业务成功的关键。海外云手机崭露头角&#xff0c;成为这一传播过程中的重要媒介…

Ubuntu22.04 gnome-builder gnome C 应用程序习练笔记(一)

一、序言 gnome-builder构建器是gnome程序开发的集成环境&#xff0c;支持主力语言C, C, Vala, jscript, python等&#xff0c;界面以最新的 gtk 4.12 为主力&#xff0c;将其下版本的gtk直接压入了depreciated&#xff0c;但gtk4.12与普遍使用的gtk3有很大区别&#xff0c;原…

第6章 智能租房——前期准备

学习目标 了解智能租房项目&#xff0c;能够说出项目中各模块包含的功能 熟悉智能租房项目的开发模式与运行机制&#xff0c;能够复述项目的开发模式与运行机制 掌握智能租房项目的创建&#xff0c;能够独立创建智能租房项目 掌握智能租房项目的配置&#xff0c;能够为智能租…

排序算法---堆排序

原创不易&#xff0c;转载请注明出处。欢迎点赞收藏~ 堆排序&#xff08;Heap Sort&#xff09;是一种基于二叉堆数据结构的排序算法。它将待排序的元素构建成一个最大堆&#xff08;或最小堆&#xff09;&#xff0c;然后逐步将堆顶元素与堆的最后一个元素交换位置&#xff0c…

求职|基于Springboot的校园求职招聘系统设计与实现(源码+数据库+文档)

校园求职招聘系统目录 目录 基于Springboot的校园求职招聘系统设计与实现 一、前言 二、系统功能设计 三、系统实现 1、用户信息管理 2、企业信息管理 3、公告类型管理 4、公告信息管理 四、数据库设计 1、实体ER图 五、核心代码 六、论文参考 七、最新计算机毕设选…

JVM-双亲委派机制

双亲委派机制定义 双亲委派机制指的是&#xff1a;当一个类加载器接收到加载类的任务时&#xff0c;会自底向上查找是否加载过&#xff0c; 再由顶向下进行加载。 详细流程 每个类加载器都有一个父类加载器。父类加载器的关系如下&#xff0c;启动类加载器没有父类加载器&am…