使用 TypeScript 的 CheckJS 为你的陈旧 JavaScript 项目续命

news2024/11/14 20:52:41

🙋 Why CheckJS?

  • 让 JavaScript 项目也能享受到 TS 的类型推导等诸多好处。* 和直迁 TypeScript 相比,大大降低成本和风险,例如:🚥 使用方法

安装依赖、追加配置

# 为你的项目安装 TypeScript
npm install typescript

# 可选的:类型定义文件,按照自己的项目需要酌情添加
npm install @types/react -D 

根目录新建 tsconfig.json,复制以下内容,特别注意黄色加粗的内容:

{"compilerOptions": {"outDir": "./FAKE_DIR","target": "ESNext","module": "CommonJS","esModuleInterop": true,"allowJs": true,"checkJs": true,"strictNullChecks": true,"jsx": "react"},"include": [// 根据项目目录结构自行配置"./src/**/*"],"exclude": [// 根据项目特性按需添加]
} 

编写类型定义

编写类型定义的时候最好有一定的约束,可以防止类型定义冲突、提高代码结构可读性,我个人推荐下面这些方案。

目录结构

一般来说,类型定义都是针对一个页面或者组件的(我们可以拿 CSS 样式文件的地位来做类比),即和组件(页面)所在文件在同一目录下,命名为 typings.d.ts:

└── src└── pages├── detail│   ├── components│   │   └── Alert│   │   ├── index.jsx│   │   ├── style.scss│   │   └── typings.d.ts│   ├── index.jsx│   ├── style.scss│   └── typings.d.ts├── home└── profile 

书写细节

d.ts 文件和 ts 文件一个最大的不同就是前者无需导入,可以理解为全局变量,这就很容易导致同名类型定义的冲突干扰,为了尽可能地解决该问题,推荐使用 namespace (命名空间)语法来分组局部类型定义,还是以上面一小节的目录结构为例,Alert 组件的 typings.d.ts 可以这样写:

declare namespace Page.Detail.Components.Alert { interface AlertProps {/** * 警告内容 */message: string;/** * 当关闭时做些什么 */onClose: () => void;}
} 

原则是根据其所属的页面、组件等层级关系划分,层级之间可以用点号隔开,以防止过多的嵌套影响美观。

其他的书写细节和 TypeScript 的写法别无二致,平时 ts 怎么写的,这里如法炮制即可。

消费方式

核心思路是通过编写 jsdoc 进行消费,下面提供几个不错的实践:

案例 1:React 函数式组件

下面的案例中使用了 React.FC 工具函数来实现。(提示:TypeScript 的各种内置 Utility Types 也是可以利用起来的)

/**
 * Alert 组件,用来展示警告信息,如:网络错误、服务器错误等
 *
 * @type {React.FC<Page.Detail.Components.Alert.AlertProps>}
 */
export const Alert = (props) => {const { message, onClose } = props;return <div>hello world!</div>;
}; 
案例 2:普通函数

对于一般函数,使用 @param 或者 @returns 注释描述该函数的入参和返回值。

/**
 * 获取用户信息描述
 *
 * @param {Page.Detail.Components.Alert.UserInfo} userInfo 用户信息
 * @return {string} 用户信息描述
 */
const getUserDescription = (userInfo) => {const {name, age} = userInfo;return `我是 ${name}, 今年 ${age} 岁`;
} 
案例 3:一般变量

对于一般变量,可以使用 @types 注释在该变量顶部描述:

/** @type {Page.Detail.Components.Alert.UserInfo} */
const userInfo = {age: 18,name: '张三',
}

// 或者也可以这样写
const user = /** @type {Page.Detail.Components.Alert.UserInfo} */ {age: 18,name: '张三',
};

// 在 return 语句中
return /** @type {Page.Detail.Components.Alert.UserInfo} */ {age: 18,name: '张三',
}; 

最后,配合 VSCode、WebStorm 等现代 IDE,你就可以享受到类型提示了!

🚨 使用时的陷阱

无法识别 d.ts 中定义的 namespace

先引入一个问题:

已知某项目是一个巨大的 monorepo,请看它的 tsconfig.json,它有什么潜在的问题?

{"compilerOptions": {"outDir": "./FAKE_DIR","target": "ESNext","module": "CommonJS","esModuleInterop": true,"allowJs": true,"checkJs": true,"jsx": "react"},"include": ["./packages/**/*","./typings"]
} 
  • 大部分情况下,monorepo 仓库下的构建产物(大部分是特别长的 JavaScript 文件)都会被打包到各自 package 下面,很容易被 include 字段匹配。* 一旦开启 allowJs = true,TypeScript Server 就会去检查这些不必要的 JavaScript 文件,从而触发性能阈值失去某些 feature,例如我们上文的 JavaScript Check 能力。

那么如何去看是什么文件造成了此问题?这里提供一个非常优雅的解法:

  • 首先打开 TS Sever Log:
  • 在大概第三十行左右的位置就可以看到 TypeScript Checker log 了所有被解析的 build 产物,这些都应该被排除在外:

在上面这个 Case 中,就可以通过 exclude 字段排除掉所有的 build 目录来提高性能:

{"compilerOptions": { // 略去},"include": ["./packages/**/*","./typings"],"exclude": ["**/build/**"]
} 

最后

为大家准备了一个前端资料包。包含54本,2.57G的前端相关电子书,《前端面试宝典(附答案和解析)》,难点、重点知识视频教程(全套)。



有需要的小伙伴,可以点击下方卡片领取,无偿分享

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

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

相关文章

冰蝎4.0特征分析及流量检测思路

0 1、 冰蝎4.0介绍 冰蝎是一款基于Java开发的动态加密通信流量的新型Webshell客户端。老牌Webshell管理神器——中国菜刀的攻击流量特征明显&#xff0c;容易被各类安全设备检测&#xff0c;实际场景中越来越少使用&#xff0c;加密 Webshell 正变得日趋流行。 由于通信流量被…

JAVA时间类及JAVA8新时间类

文章目录Java旧时间类关系图![在这里插入图片描述](https://img-blog.csdnimg.cn/e2c2c26c841e40bdb9cc85d0fc4bc1df.png)GMT、时间戳、统一标准时间、时区Java时间类创建时间类示例java.text.DateFormat时间格式转换java.util.Calendar总结Java时间类Java8新时间类InstantCloc…

Vulnhub-DC-2实战靶场

Vulnhub-DC-2实战靶场 https://blog.csdn.net/ierciyuan/article/details/127560871 这次试试DC-2&#xff0c;目标是找到官方设置的5个flag。 一. 环境搭建 1. 准备工具 虚拟机Kali&#xff1a; 自备&#xff0c;我的kali的IP为192.168.3.129 靶场机&#xff1a; https…

接口和抽象类

接口(Interface)和抽象类(Abstract Class)是支持抽象类定义的两种机制。 1.抽象类 (1)说明 在Java中被abstract关键字修饰的类称为抽象类&#xff0c;被abstract关键字修饰的方法称为抽象方法&#xff0c;抽象方法只有方法的声明&#xff0c;没有方法体。抽象类是用来捕捉子…

CCNP350-401学习笔记(151-200题)

151、Which two LISP infrastructure elements are needed to support LISP to non-LISP internetworking? (Choose two.)A. PETR B. PITRC. MR D. MS E. ALT 152、In an SD-WAN deployment, which action in the vSmart controller responsible for? A. handle, maintain, …

一文搞懂C/C++内存管理原理与实现

C 语言内存管理指对系统内存的分配、创建、使用这一系列操作。在内存管理中&#xff0c;由于是操作系统内存&#xff0c;使用不当会造成毕竟麻烦的结果。本文将从系统内存的分配、创建出发&#xff0c;并且使用例子来举例说明内存管理不当会出现的情况及解决办法。 一、内存 …

[python入门㊽] - 自定义异常 raise 关键字

目录 ❤ 自定义抛出异常关键字 - raise ❤ 使用raise主动引发异常 ❤ raise 关键字的用法 ❤ 触发异常 ❤ 自定义异常类 在前面我们学过异常三个关键字分别是try、except 以及 finally 在编程过程中合理的使用异常可以使得程序正常的执行。有直接抛出异常的形式&…

【HTML】HTML 表格总结 ★★★ ( 表格标签 | 行标签 | 单元格标签 | 表格标签属性 | 表头单元格标签 | 表格标题标签 | 合并单元格 )

文章目录一、表格标签组成 ( 表格标签 | 行标签 | 单元格标签 )二、table 表格属性 ( border 属性 | align 属性 | width 属性 | height 属性 )三、表头单元格标签四、表格标题标签五、合并单元格1、合并单元格方式2、合并单元格顺序3、合并单元格流程六、合并单元格示例1、原始…

Linux之ping\kill\killall命令

参考视频&#xff1a;linux命令&#xff08;ping&#xff09;linux命令&#xff08;kill、killall&#xff09;Linux ping 命令用于检测主机。执行 ping 指令会使用 ICMP 传输协议&#xff0c;发出要求回应的信息&#xff0c;若远端主机的网络功能没有问题&#xff0c;就会回应…

Redis进阶:布隆过滤器(Bloom Filter)及误判率数学推导

1 缘起 有一次偶然间听到有同事在说某个项目中使用了布隆过滤器&#xff0c; 哎呦&#xff0c;我去&#xff0c;我竟然不知道啥是布隆过滤器&#xff0c; 这我哪能忍&#xff1f;其实&#xff0c;也可以忍&#xff0c;但是&#xff0c;可能有的面试官不能忍&#xff01;&#…

简介JVM

目录 一、内存分区 1、程序计数器 2、栈 3、堆 4、方法区 二、类加载 1、Loading 2、Linking Verification Preparation Resolution 3、Initializing 4、双亲委派模型 三、垃圾回收 1、如何判断为垃圾&#xff1f; 引入引用计数 可达性分析 2、如…

Transformer论文阅读:Swin Transformer算法笔记

标题&#xff1a;Swin Transformer: Hierarchical Vision Transformer using Shifted Windows 会议&#xff1a;ICCV2021 论文地址&#xff1a;https://ieeexplore.ieee.org/document/9710580/ 官方代码&#xff1a;https://github.com/microsoft/Swin-Transformer 作者单位&am…

[安装之2] 台式计算机加固态硬盘,台式机添加固态硬盘教程_台式主机固态硬盘怎么安装

固态硬盘是用固态电子存储芯片阵列制成的硬盘&#xff0c;也是电脑中比较常见的内存硬件&#xff0c;有些用户在使用电脑时候&#xff0c;由于内存不足导致系统运行较卡的情况&#xff0c;往往会选择添加固态硬盘来解决&#xff0c;那么台式主机固态硬盘怎么安装呢&#xff1f;…

shell脚本内调用另外一个shell脚本的几种方法

有时会在一个shell脚本(如test_call_other_shell.sh)中调用另外一个shell脚本(如parameter_usage.sh)&#xff0c;这里总结几种可行的方法&#xff0c;这些方法在linux上和windows上(通过Git Bash)均适用&#xff1a; 1.通过source: 运行在相同的进程&#xff0c;在test_…

CCIE重认证-300-401-拖图题全

拖图 拖图题 编程 snippet&#xff1b;192.168.5.0&#xff0c;mask 255.255.255.0&#xff1b;number是192.168.5.0&#xff1b;mask是255.255.255.0 snippets&#xff1b;edit-config对config&#xff0c;loopback对name 100&#xff0c;address对primary&#xff0c;mask…

广度优先搜索算法 - 迷宫找路

广度优先搜索算法1 思考问题1.1 这个迷宫需不需要指定入口和出口&#xff1f;2 先粗略实现2.1 源码2.2 源码解释3 优化代码3.1 优化读取文件部分3.2 增加错误处理4 再优化-让程序变得更加灵活4.1 用户外部可以循环输入入口和出口5 完整代码这是一个提问者的提出的问题&#xff…

制造业的云ERP在外网怎么访问?内网服务器一步映射到公网

随着企业信息化、智能化时代的到来&#xff0c;很多制造业企业都在用云ERP。用友U 9cloud通过双版本公有云专属、私有云订阅、传统软件购买三种模式满足众多制造业企业的需求&#xff0c;成为一款适配中型及中大型制造业的云ERP&#xff0c;是企业数智制造的创新平台。 用友U 9…

python 面向对象利用selenium【获取某东商品信息】

用python程序和谷歌selenium插件获取某东商品详细信息【商品名称、商品简介&#xff0c;超链接】利用selenium自动化程序 中的css页面结构索取来获取详细数据关于谷歌selenium的安装方法和使用方法第一步检查自己谷歌浏览器的版本1.1 找到设置&#xff1a;并鼠标点击进入1.2进入…

排序评估指标——NDCG和MAP

在搜索和推荐任务中&#xff0c;系统常返回一个item列表。如何衡量这个返回的列表是否优秀呢&#xff1f; 例如&#xff0c;当我们检索【推荐排序】&#xff0c;网页返回了与推荐排序相关的链接列表。列表可能会是[A,B,C,G,D,E,F],也可能是[C,F,A,E,D]&#xff0c;现在问题来了…

使用canvas写一个flappy bird小游戏

简介 canvas 是HTML5 提供的一种新标签&#xff0c;它可以支持 JavaScript 在上面绘画&#xff0c;控制每一个像素&#xff0c;它经常被用来制作小游戏&#xff0c;接下来我将用它来模仿制作一款叫flappy bird的小游戏。flappy bird&#xff08;中文名&#xff1a;笨鸟先飞&am…