写点什么

Hegel:立志成为最好的 JavaScript 静态类型检查器

2020 年 5 月 29 日

Hegel:立志成为最好的 JavaScript 静态类型检查器

Hegel 作为 JavaScript 类型检查器中的新秀,立志要成为最好的 JavaScript 静态类型检查器。它宣称提供了一个具备强类型推断的可靠的类型系统。目前 Hegel 还在 alpha 测试阶段,大家可以在其提供的专用在线练习场进行功能体验。


Hegel 是一个类型注解可选的 JavaScript 类型检查器,同时它和 TypeScript 一样,使用者不需要重新学习一门新的语言结构,只需要掌握注解的语法。Hegel 希望通过强大的、稳定的类型系统,尽量避免程序在运行时由于类型错误产生的异常。下面的代码展示了其强大的类型检查能力:


// 定义numbers的类型为Array<number>const numbers: Array<number> = [];// 将numbers变量赋值给numbersOrStrings, 但其类型为Array<string | number>// Hegel会检查出类型错误:// HegelError:类型"Array<number>"和类型"Array<number | string>"不兼容const numbersOrStrings: Array<string | number> = numbers;// 给numbersOrStrings第二个元素赋值numbersOrStrings[1] = "Hello, TypeError!";// 下面的代码 Hegel会检查出类型异常:// HegelError: 属性"toFixed"在 "Number | undefined"中不存在numbers[1].toFixed(1);
复制代码


上面的代码使用TypeScript(v3.8.3)进行编译时没有任何错误,但是在实际运行时确会抛出异常。


译者注:

JS 运行时,numbers 和 numbersOrStrings 都是引用类型。他们在相互赋值的时候,属于引用赋值。因此 numbersOrStrings 修改元素内容的时候,对 numbers 也同样有效果。所以在执行 numbers[1].toFixed(1)时候,就会报错,因为字符串没有 toFixed 函数。上面的代码体现了 Hegel 可靠的类型系统。


除了可靠的类型系统,健壮的类型推断也是 Hegel 的主要设计目标。示例代码如下:


// Hegel会推断"promisify"是"<_q, _c>((_c) => _q) => (_c) => Promise<_q>"const  promisify = fn => arg => Promise.resolve(fn(arg));// 这里,Hegel会推断为 "<_c>(_c) => Promise<_c>" const id =  promisify(x  => x)// 同样,"upperStr"会被推断为 "Promise<string>"const upperStr = id("It will be inferred").then(str => str.toUpperCase()// 最后"twiceNum"将会被推断为"Promise<number>"const twicedNum =  id(42).then(num  => num **  2);  
复制代码


在TypeScript(测试版本:3.7.5)中运行相同的代码时,TS 会识别 3 个异常,同时会将变量result推断为Promise<any>类型。 因此健壮的类型推断允许开发人员尽量少的编写代码注释,这样反而更有利于代码的可读性。


Hegel 将异常也纳入了类型检查中,示例代码如下:


function  assert(age)  {  if  (typeof age !==  "number")  {    throw  new  TypeError("Age is not number.");  }    if  (age <=  0)  {    throw  new  ReferenceError("Age can't be less or equals zero.");  }}try  {  assert(0);}  catch(error)  {  // 这里的"error"变量,被推断为"ReferenceError | TypeError | unknown"}
复制代码


Hegel 的缺点是不支持强制类型转换和any类型,示例如下:


// Error: Hegel中不存在 any 类型const something:  any  =  null;// Error: Hegel中不支持类型转换(null:  any).call();
复制代码


在 Hegel 文档中说明了其与主流类型检查器(TypeScript 和 Flow)的对比。除了支持标准类型(基础类型、函数、对象、类、数组)之外,Hegel 的类型系统还支持了未知类型(例如由 JSON.parse()返回的类型)、可选类型、联合类型、元祖类型、类型别名、泛类型和可变类型。这也是 Hegel 的特性之一。


可变类型可以帮助我们从现有类型提取或者创建新类型。因此,可变类型可以理解为从一个类型生成另一个类型的函数。在 Hegel 中,定义了17个可变类型


下面是可变类型$Exclude (语义上和 TypeScript 中的 Exclude 类型类似)的示例代码:


// 定义类型type  Status  =  "Ok"  |  "Failed"  |  "Pending"  |  "Canceled";// 使用 可变类型之后// IntermediateStatuses = "Canceled" | "Panding"type  IntermediateStatuses  = $Exclude<Status,  "Ok"  |  "Failed">;// 赋值const intermediateStatuses:  Array<$Exclude<Status,  "Ok"  |  "Failed">>  =  ["Pending",  "Canceled"];// Hegel 类型检查异常:// Error: 类型"['Failed']"和类型"...Array<'Canceled' | 'Pending'>"不兼容intermediateStatuses.push("Failed");
复制代码


parceljs的作者,Devon Govett 在 Twitter 上感慨说:


Hegel 看上去很有趣,它比 TS 更接近 Flow,而且是使用 JS 实现的。专注于类型推断和健壮类型,只有 JS 和类型(没有额外的功能)。支持.d.ts、vscode 集成,等等…。


Hegel 发布在 npm 上,提供了一个命令行工具和一个可交互的在线体验区。同时,其在GitHub仓库提供了对应的安装命令,要求 node.js 最低版本为 12。


Hegel 是基于 MIT 协议的。欢迎大家在该项目的 GitHub 上进行反馈和贡献。另外,Hegel 的作者也声明:


Hegel 源于社区,奉献社区;因此,你的任何 PRs 和 issues 都不会被忽略和遗忘。


原文链接:


https://www.infoq.com/news/2020/05/hegel-type-checking-javascript/


2020 年 5 月 29 日 10:00850

评论 2 条评论

发布
用户头像
立志
2020 年 05 月 30 日 17:30
回复
嘿嘿
2020 年 06 月 02 日 22:02
回复
没有更多了
发现更多内容

训练营第五周总结

大脸猫

极客大学架构师训练营

架构师训练营第 1 期 -- 第九周作业

发酵的死神

极客大学架构师训练营

架构师训练营第九周学习笔记

郎哲

极客大学架构师训练营

第 5 周 系统架构总结

心在那片海

架构师训练营week09

FG佳

极客大学架构师训练营

第五周总结

Griffenliu

架构师训练营 2 期 - 第五周总结

Geek_no_one

极客大学架构师训练营

「架构师训练营第 1 期」第九周作业

张国荣

架构师训练营作业

郎哲

极客大学架构师训练营

java实现一致性 hash 算法

Mars

一致性Hash算法

架构师训练营第九周学习总结

文智

极客大学架构师训练营

架构师训练营第九周作业

Shunyi

极客大学架构师训练营

架构师训练营 - 作业 - 第九周

Max2@12

五周 - 作业

水浴清风

一致性hash

性能优化(三)

wing

极客大学架构师训练营

架构师训练营第九周作业

邓昀垚

极客大学架构师训练营

第九周作业

TheSRE

极客大学架构师训练营

「架构师训练营」第 5 周作业

小黄鱼

极客大学架构师训练营

架构2期第5周作业

supersky6

第五周笔记

willson

极客大学架构师训练营

架构师训练营 - 第九周 - 作业一

行者

第九周总结

solike

顺序查找

ilovealt

算法和数据结构

第 5 周 系统架构作业

心在那片海

架构师训练营 2 期 - 第5周命题作业

Geek_no_one

极客大学架构师训练营

第九周总结

Geek_ac4080

Python进阶——如何正确使用魔法方法?(上)

Kaito

Python

第五周作业

Griffenliu

架构一期 第九周作业

haha

极客大学架构师训练营

架构师训练营 - 第 9 周课后作业(1 期)

阿甘

架构师训练营第九周总结

邓昀垚

极客大学架构师训练营

微服务架构下如何保证事务的一致性

微服务架构下如何保证事务的一致性

Hegel:立志成为最好的 JavaScript 静态类型检查器-InfoQ