当前位置: 首页 > news >正文

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 类型体操通关秘籍》

最后

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

相关文章:

  • SQL Parser
  • Docker学习历程
  • 2024/2最新升级ChatGPT Plus的方法
  • Mybatis中的sql-xml延迟加载机制
  • RocketMQ(二):领域模型(生产者、消费者)
  • 【C#】.net core 6.0 设置根目录下某个文件夹可访问,访问创建的图片等资源
  • 【每日一题】LeetCode——链表的中间结点
  • CTFshow web(php命令执行 45-49)
  • 《Python 网络爬虫简易速速上手小册》第7章:如何绕过反爬虫技术?(2024 最新版)
  • C语言的循环结构
  • Unity笔记:相机移动
  • VSCode 文件夹增加右键打开
  • Git详细讲解
  • 逆向工程:揭开科技神秘面纱的艺术
  • 华为配置访客接入WLAN网络示例(MAC优先的Portal认证)
  • 实现windows 窗体的自己画,网上摘抄的,学习了
  • Dubbo 整合 Pinpoint 做分布式服务请求跟踪
  • java8 Stream Pipelines 浅析
  • javascript 哈希表
  • node.js
  • RedisSerializer之JdkSerializationRedisSerializer分析
  • vue2.0开发聊天程序(四) 完整体验一次Vue开发(下)
  • Wamp集成环境 添加PHP的新版本
  • 配置 PM2 实现代码自动发布
  • 一、python与pycharm的安装
  • 再次简单明了总结flex布局,一看就懂...
  • UI设计初学者应该如何入门?
  • 进程与线程(三)——进程/线程间通信
  • # 飞书APP集成平台-数字化落地
  • #LLM入门|Prompt#1.7_文本拓展_Expanding
  • #微信小程序:微信小程序常见的配置传旨
  • (14)Hive调优——合并小文件
  • (31)对象的克隆
  • (done) NLP “bag-of-words“ 方法 (带有二元分类和多元分类两个例子)词袋模型、BoW
  • (二)构建dubbo分布式平台-平台功能导图
  • (附源码)springboot宠物管理系统 毕业设计 121654
  • (附源码)计算机毕业设计SSM保险客户管理系统
  • (三维重建学习)已有位姿放入colmap和3D Gaussian Splatting训练
  • (十五)Flask覆写wsgi_app函数实现自定义中间件
  • .L0CK3D来袭:如何保护您的数据免受致命攻击
  • .MyFile@waifu.club.wis.mkp勒索病毒数据怎么处理|数据解密恢复
  • .Net 8.0 新的变化
  • .NET Framework 3.5中序列化成JSON数据及JSON数据的反序列化,以及jQuery的调用JSON
  • .NET 中让 Task 支持带超时的异步等待
  • .net快速开发框架源码分享
  • .sdf和.msp文件读取
  • @JoinTable会自动删除关联表的数据
  • @Not - Empty-Null-Blank
  • @Query中countQuery的介绍
  • @staticmethod和@classmethod的作用与区别
  • [ vulhub漏洞复现篇 ] JBOSS AS 4.x以下反序列化远程代码执行漏洞CVE-2017-7504
  • []指针
  • [100天算法】-目标和(day 79)
  • [1181]linux两台服务器之间传输文件和文件夹
  • [2009][note]构成理想导体超材料的有源THz欺骗表面等离子激元开关——